Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NFT standard #177

Merged
merged 60 commits into from
Nov 8, 2022
Merged
Show file tree
Hide file tree
Changes from 58 commits
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
048e6bf
starting of nft standard
ailisp Jul 25, 2022
63c6520
Merge branch 'develop' into nft-standard
ailisp Jul 25, 2022
a2dda0f
more utils and struct definitions
ailisp Jul 25, 2022
cc5f55b
merge develop
ailisp Aug 9, 2022
a89f0ef
convert to typescript, model events
ailisp Aug 10, 2022
272cec2
finish NonFungibleToken constructor
ailisp Aug 11, 2022
1d65a28
implement internal transfer
ailisp Aug 15, 2022
01db54b
implement all core_impl before receiver and resolver
ailisp Aug 16, 2022
78a6328
add missing files
ailisp Aug 16, 2022
33023a8
finish nft_resolve part
ailisp Aug 16, 2022
0d850a4
Merge develop into nft-standard
near-bulldozer[bot] Aug 16, 2022
8afe149
Merge refs/heads/develop into nft-standard
near-bulldozer[bot] Aug 16, 2022
6647953
Merge refs/heads/develop into nft-standard
near-bulldozer[bot] Aug 18, 2022
92de935
Merge refs/heads/develop into nft-standard
near-bulldozer[bot] Aug 19, 2022
8b8dc76
resolve conflict
ailisp Sep 15, 2022
58ed9ce
resolve conflict
ailisp Sep 15, 2022
fb7f2de
Merge branch 'develop' into nft-standard
ailisp Sep 16, 2022
b37397e
merge develop, format and wip fix lint
ailisp Sep 26, 2022
750249e
fix lint
ailisp Sep 26, 2022
fc27f3c
updates to nft standard
ailisp Sep 29, 2022
650979c
resolve conflicts
ailisp Oct 13, 2022
6106ee4
format
ailisp Oct 13, 2022
3ae3573
remove cli
ailisp Oct 13, 2022
723f537
clean up
ailisp Oct 13, 2022
eb5ade9
fix using new nested api, promise result api, etc.
ailisp Oct 13, 2022
f64127d
fix tsc errors
ailisp Oct 14, 2022
c47c32a
build pass
ailisp Oct 14, 2022
58ce031
majority of nft standard is implemented
ailisp Oct 14, 2022
2a00cc3
Merge branch 'develop' into nft-standard
ailisp Oct 17, 2022
f332fd9
implement core and metadata provider
ailisp Oct 17, 2022
373c193
first nft standard test
ailisp Oct 18, 2022
c91e325
figure out reconstruct puzzle
ailisp Oct 19, 2022
4e2065d
fix first test
ailisp Oct 20, 2022
cdc8422
mint test pass
ailisp Oct 20, 2022
49f9e9b
simple transfer fully work
ailisp Oct 21, 2022
22807e9
add token receiver
ailisp Oct 24, 2022
81ffc9d
fix transfer call fast return test
ailisp Oct 25, 2022
b47e424
add all core tests
ailisp Oct 25, 2022
ba57c23
reorganize code because ts interface must be impl in place, unlike ru…
ailisp Oct 26, 2022
b900966
implement approval, approval receiver interface and make an example a…
ailisp Oct 27, 2022
1e9ac1d
add and fix simple approve test
ailisp Oct 28, 2022
bbb300c
add and fix all approval tests
ailisp Oct 31, 2022
128a4e4
add nft enum implementation
ailisp Nov 1, 2022
8473065
add approval tests, lint, format
ailisp Nov 2, 2022
e7bf52a
resolve conflict
ailisp Nov 2, 2022
1990900
yarn build
ailisp Nov 2, 2022
e8fe9f7
fix ci
ailisp Nov 2, 2022
e30dc24
revert cli from develop
ailisp Nov 3, 2022
64a233f
revert unrelated files
ailisp Nov 3, 2022
0bfd74e
add most docs strings
ailisp Nov 3, 2022
c4dc81e
Merge branch 'develop' into nft-standard
volovyks Nov 3, 2022
7ff97f5
example standard contract use near-contract-standards as external dep…
ailisp Nov 4, 2022
50db903
Merge branch 'nft-standard' of github.com:near/near-sdk-js into nft-s…
ailisp Nov 4, 2022
bc80ae3
lint format
ailisp Nov 4, 2022
a56eeab
Merge branch 'develop' into nft-standard
ailisp Nov 4, 2022
3df19a6
try fix link in ci
ailisp Nov 4, 2022
f8b4fce
Merge branch 'nft-standard' of github.com:near/near-sdk-js into nft-s…
ailisp Nov 4, 2022
36708b2
Address Serhii's comments
ailisp Nov 4, 2022
ea95d69
fix all account id and token ids in nft standard
ailisp Nov 4, 2022
9ef0c92
make nft standard taking object arguments instead of positional
ailisp Nov 8, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .gitattributes
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
yarn.lock linguist-generated=true -diff
lib/**/*.js linguist-generated=true -diff
lib/**/*.d.ts linguist-generated=true -diff
lib/**/*.d.ts linguist-generated=true -diff
near-contract-standards/lib/**/*.js linguist-generated=true -diff
near-contract-standards/lib/**/*.d.ts linguist-generated=true -diff
2 changes: 2 additions & 0 deletions .github/workflows/examples.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,5 @@ jobs:
run: cd examples && yarn build:status-message && yarn test:status-message
- name: parking-lot
run: cd examples && yarn build:parking-lot && yarn test:parking-lot
- name: standard nft
run: cd examples && yarn build-nft && yarn test:nft
258 changes: 258 additions & 0 deletions examples/__tests__/standard-nft/test_approval.ava.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,258 @@
import { Worker } from "near-workspaces";
import test from "ava";

test.beforeEach(async (t) => {
// Init the worker and start a Sandbox server
const worker = await Worker.init();

// Prepare sandbox for tests, create accounts, deploy contracts, etx.
const root = worker.rootAccount;

// Deploy status-message the contract.
const nft = await root.devDeploy("./build/my-nft.wasm");

// Create test accounts
const ali = await root.createSubAccount("alice");
const bob = await root.createSubAccount("bob");
const nftOwner = await root.createSubAccount("owner");
const nftReceiver = await root.devDeploy("./build/nft-receiver.wasm");
const approvalReceiver = await root.devDeploy(
"./build/nft-approval-receiver.wasm"
);

await nft.call(nft, "init", {
owner_id: nftOwner.accountId,
metadata: { spec: "nft-1.0.0", name: "My NFT", symbol: "NFT" },
});

await nftReceiver.call(nftReceiver, "init", nft.accountId);
await nftReceiver.call(approvalReceiver, "init", nft.accountId);

let token_metadata = {
title: "Olympus Mons",
description: "The tallest mountain in the charted solar system",
media: null,
media_hash: null,
copies: 1,
issued_at: null,
expires_at: null,
starts_at: null,
updated_at: null,
extra: null,
reference: null,
reference_hash: null,
};
await nftOwner.call(
nft,
"nft_mint",
["0", nftOwner.accountId, token_metadata],
{ attachedDeposit: "10 mN" }
);

// Save state for test runs, it is unique for each test
t.context.worker = worker;
t.context.accounts = {
root,
nft,
ali,
bob,
nftOwner,
nftReceiver,
approvalReceiver,
};
});

test.afterEach.always(async (t) => {
await t.context.worker.tearDown().catch((error) => {
console.log("Failed tear down the worker:", error);
});
});

test("Simple approve", async (t) => {
const { ali, bob, nft, nftOwner } = t.context.accounts;

let res = await nftOwner.callRaw(
nft,
"nft_approve",
["0", ali.accountId, null],
{ attachedDeposit: "510000000000000000000" }
);
t.assert(res.result.status.SuccessValue);

let alice_approved = await nft.view("nft_is_approved", [
"0",
ali.accountId,
null,
]);
t.assert(alice_approved);

let alice_approval_id_is_1 = await nft.view("nft_is_approved", [
"0",
ali.accountId,
"1",
]);
t.assert(alice_approval_id_is_1);

let alice_approval_id_is_2 = await nft.view("nft_is_approved", [
"0",
ali.accountId,
"2",
]);
t.assert(!alice_approval_id_is_2);

res = await nftOwner.callRaw(nft, "nft_approve", ["0", ali.accountId, null], {
attachedDeposit: "1",
});
t.assert(res.result.status.SuccessValue);
alice_approval_id_is_2 = await nft.view("nft_is_approved", [
"0",
ali.accountId,
"2",
]);
t.assert(alice_approval_id_is_2);

res = await nftOwner.callRaw(nft, "nft_approve", ["0", bob.accountId, null], {
attachedDeposit: "450000000000000000000",
});
t.assert(res.result.status.SuccessValue);

let bob_approval_id_is_3 = await nft.view("nft_is_approved", [
"0",
bob.accountId,
"3",
]);
t.assert(bob_approval_id_is_3);
});

test("Approve call", async (t) => {
const { nft, nftOwner, approvalReceiver } = t.context.accounts;

let res = await nftOwner.call(
nft,
"nft_approve",
["0", approvalReceiver.accountId, "return-now"],
{ attachedDeposit: "450000000000000000000", gas: "300 Tgas" }
);
t.is(res, "cool");

res = await nftOwner.call(
nft,
"nft_approve",
["0", approvalReceiver.accountId, "hahaha"],
{ attachedDeposit: "1", gas: "300 Tgas" }
);
t.is(res, "hahaha");
});

test("Approved account transfers token", async (t) => {
const { ali, nft, nftOwner } = t.context.accounts;

let res = await nftOwner.callRaw(
nft,
"nft_approve",
["0", ali.accountId, null],
{ attachedDeposit: "510000000000000000000" }
);
t.assert(res.result.status.SuccessValue);

let token = await nft.view("nft_token", "0");
t.is(token.owner_id, nftOwner.accountId);

res = await ali.callRaw(
nft,
"nft_transfer",
[ali.accountId, "0", null, "gotcha! bahahaha"],
{ attachedDeposit: "1" }
);
t.is(res.result.status.SuccessValue, "");

token = await nft.view("nft_token", "0");
t.is(token.owner_id, ali.accountId);
});

test("revoke", async (t) => {
const { ali, bob, nft, nftOwner } = t.context.accounts;

let res = await nftOwner.callRaw(
nft,
"nft_approve",
["0", ali.accountId, null],
{ attachedDeposit: "510000000000000000000" }
);
t.assert(res.result.status.SuccessValue);

res = await nftOwner.callRaw(nft, "nft_approve", ["0", bob.accountId, null], {
attachedDeposit: "510000000000000000000",
});
t.assert(res.result.status.SuccessValue);

res = await nftOwner.callRaw(nft, "nft_revoke", ["0", ali.accountId], {
attachedDeposit: "1",
});
t.is(res.result.status.SuccessValue, "");

let alice_approved = await nft.view("nft_is_approved", [
"0",
ali.accountId,
null,
]);
t.assert(!alice_approved);

let bob_approved = await nft.view("nft_is_approved", [
"0",
bob.accountId,
null,
]);
t.assert(bob_approved);

res = await nftOwner.callRaw(nft, "nft_revoke", ["0", bob.accountId], {
attachedDeposit: "1",
});
t.is(res.result.status.SuccessValue, "");

alice_approved = await nft.view("nft_is_approved", [
"0",
ali.accountId,
null,
]);
t.assert(!alice_approved);

bob_approved = await nft.view("nft_is_approved", ["0", bob.accountId, null]);
t.assert(!bob_approved);
});

test("revoke all", async (t) => {
const { ali, bob, nft, nftOwner } = t.context.accounts;

let res = await nftOwner.callRaw(
nft,
"nft_approve",
["0", ali.accountId, null],
{ attachedDeposit: "510000000000000000000" }
);
t.assert(res.result.status.SuccessValue);

res = await nftOwner.callRaw(nft, "nft_approve", ["0", bob.accountId, null], {
attachedDeposit: "510000000000000000000",
});
t.assert(res.result.status.SuccessValue);

res = await nftOwner.callRaw(nft, "nft_revoke_all", "0", {
attachedDeposit: "1",
});
t.is(res.result.status.SuccessValue, "");

let alice_approved = await nft.view("nft_is_approved", [
"0",
ali.accountId,
null,
]);
t.assert(!alice_approved);

let bob_approved = await nft.view("nft_is_approved", [
"0",
bob.accountId,
null,
]);
t.assert(!bob_approved);
});
Loading