Skip to content

Commit d361888

Browse files
authoredOct 13, 2022
Merge branch 'develop' into develop
2 parents 1893d16 + 56d31cc commit d361888

6 files changed

+451
-147
lines changed
 
+175-40
Original file line numberDiff line numberDiff line change
@@ -1,60 +1,187 @@
1-
import { Worker } from "near-workspaces";
1+
import { Worker, NEAR } from "near-workspaces";
22
import test from "ava";
33

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

8-
// Prepare sandbox for tests, create accounts, deploy contracts, etx.
9-
const root = worker.rootAccount;
7+
const totalSupply = 1000;
8+
const yoctoAccountStorage = "90";
109

11-
// Deploy the ft contract.
12-
const ft = await root.devDeploy("./build/fungible-token.wasm");
10+
const root = worker.rootAccount;
1311
const xcc = await root.devDeploy("./build/fungible-token-helper.wasm");
12+
const ft = await root.createSubAccount("ft");
13+
await ft.deploy("./build/fungible-token.wasm");
14+
await root.call(ft, "init", {
15+
owner_id: root.accountId,
16+
total_supply: totalSupply.toString(),
17+
});
18+
const alice = await root.createSubAccount("alice", {
19+
initialBalance: NEAR.parse("10 N").toJSON(),
20+
});
1421

15-
// Init the contracts
16-
await ft.call(ft, "init", { prefix: "a", totalSupply: "1000" });
17-
18-
// Create test accounts
19-
const ali = await root.createSubAccount("ali");
20-
const bob = await root.createSubAccount("bob");
21-
22-
// Save state for test runs, it is unique for each test
2322
t.context.worker = worker;
24-
t.context.accounts = { root, ft, ali, bob, xcc };
23+
t.context.accounts = { root, ft, alice, xcc };
24+
t.context.variables = { totalSupply, yoctoAccountStorage };
2525
});
2626

2727
test.afterEach.always(async (t) => {
2828
await t.context.worker.tearDown().catch((error) => {
29-
console.log("Failed tear down the worker:", error);
29+
console.log("Failed to tear down the worker:", error);
3030
});
3131
});
3232

33+
test("should register account and pay for storage", async (t) => {
34+
const { ft, alice } = t.context.accounts;
35+
const { yoctoAccountStorage } = t.context.variables;
36+
const result = await alice.call(
37+
ft,
38+
"storage_deposit",
39+
{ account_id: alice.accountId },
40+
{ attachedDeposit: NEAR.parse("1 N").toJSON() }
41+
);
42+
const aliceAfterBalance = await alice.balance();
43+
const expected = {
44+
message: `Account ${alice.accountId} registered with storage deposit of ${yoctoAccountStorage}`,
45+
};
46+
t.deepEqual(result, expected);
47+
t.true(
48+
aliceAfterBalance.total > NEAR.parse("9 N").toJSON(),
49+
"alice should have received a refund"
50+
);
51+
});
52+
53+
test("should return message when account is already registered and not refund when no deposit is attached", async (t) => {
54+
const { ft, alice } = t.context.accounts;
55+
const { yoctoAccountStorage } = t.context.variables;
56+
const result = await alice.call(
57+
ft,
58+
"storage_deposit",
59+
{ account_id: alice.accountId },
60+
{ attachedDeposit: NEAR.parse("1 N").toJSON() }
61+
);
62+
const expected = {
63+
message: `Account ${alice.accountId} registered with storage deposit of ${yoctoAccountStorage}`,
64+
};
65+
t.deepEqual(result, expected);
66+
const result2 = await alice.call(
67+
ft,
68+
"storage_deposit",
69+
{ account_id: alice.accountId },
70+
{ attachedDeposit: NEAR.parse("0 N").toJSON() }
71+
);
72+
t.is(result2.message, "Account is already registered");
73+
});
74+
75+
test("should return message and refund predecessor caller when trying to pay for storage for an account that is already registered", async (t) => {
76+
const { ft, alice } = t.context.accounts;
77+
const { yoctoAccountStorage } = t.context.variables;
78+
const result = await alice.call(
79+
ft,
80+
"storage_deposit",
81+
{ account_id: alice.accountId },
82+
{ attachedDeposit: NEAR.parse("1 N").toJSON() }
83+
);
84+
const expected = {
85+
message: `Account ${alice.accountId} registered with storage deposit of ${yoctoAccountStorage}`,
86+
};
87+
t.deepEqual(result, expected);
88+
const result2 = await alice.call(
89+
ft,
90+
"storage_deposit",
91+
{ account_id: alice.accountId },
92+
{ attachedDeposit: NEAR.parse("1 N").toJSON() }
93+
);
94+
t.is(
95+
result2.message,
96+
"Account is already registered, deposit refunded to predecessor"
97+
);
98+
const aliceBalance = await alice.balance();
99+
t.is(
100+
aliceBalance.total > NEAR.parse("9 N"),
101+
true,
102+
"alice should have received a refund"
103+
);
104+
});
105+
106+
test("should return message when trying to pay for storage with less than the required amount and refund predecessor caller", async (t) => {
107+
const { ft, alice } = t.context.accounts;
108+
const { yoctoAccountStorage } = t.context.variables;
109+
const result = await alice.call(
110+
ft,
111+
"storage_deposit",
112+
{ account_id: alice.accountId },
113+
{ attachedDeposit: NEAR.from("40").toJSON() }
114+
);
115+
t.is(
116+
result.message,
117+
`Not enough attached deposit to cover storage cost. Required: ${yoctoAccountStorage}`
118+
);
119+
});
120+
121+
test("should throw when trying to transfer for an unregistered account", async (t) => {
122+
const { ft, alice, root } = t.context.accounts;
123+
try {
124+
await root.call(
125+
ft,
126+
"ft_transfer",
127+
{ receiver_id: alice.accountId, amount: "1" },
128+
{ attachedDeposit: NEAR.from("1").toJSON() }
129+
);
130+
} catch (error) {
131+
t.true(
132+
error.message.includes(`Account ${alice.accountId} is not registered`)
133+
);
134+
}
135+
});
136+
33137
test("Owner has all balance in the beginning", async (t) => {
34-
const { ft } = t.context.accounts;
35-
const result = await ft.view("ftBalanceOf", { accountId: ft.accountId });
138+
const { ft, root } = t.context.accounts;
139+
const result = await ft.view("ft_balance_of", { account_id: root.accountId });
36140
t.is(result, "1000");
37141
});
38142

39143
test("Can transfer if balance is sufficient", async (t) => {
40-
const { ali, ft } = t.context.accounts;
41-
42-
await ft.call(ft, "ftTransfer", { receiverId: ali.accountId, amount: "100" });
43-
const aliBalance = await ft.view("ftBalanceOf", { accountId: ali.accountId });
144+
const { alice, ft, root } = t.context.accounts;
145+
await alice.call(
146+
ft,
147+
"storage_deposit",
148+
{ account_id: alice.accountId },
149+
{ attachedDeposit: NEAR.parse("1 N").toJSON() }
150+
);
151+
await root.call(
152+
ft,
153+
"ft_transfer",
154+
{ receiver_id: alice.accountId, amount: "100" },
155+
{ attachedDeposit: NEAR.from("1").toJSON() }
156+
);
157+
const aliBalance = await ft.view("ft_balance_of", {
158+
account_id: alice.accountId,
159+
});
44160
t.is(aliBalance, "100");
45-
const ownerBalance = await ft.view("ftBalanceOf", {
46-
accountId: ft.accountId,
161+
const ownerBalance = await ft.view("ft_balance_of", {
162+
account_id: root.accountId,
47163
});
48164
t.is(ownerBalance, "900");
49165
});
50166

51167
test("Cannot transfer if balance is not sufficient", async (t) => {
52-
const { ali, bob, ft } = t.context.accounts;
168+
const { alice, root, ft } = t.context.accounts;
169+
await alice.call(
170+
ft,
171+
"storage_deposit",
172+
{ account_id: alice.accountId },
173+
{ attachedDeposit: NEAR.parse("1 N").toJSON() }
174+
);
53175
try {
54-
await ali.call(ft, "ftTransfer", {
55-
receiverId: bob.accountId,
56-
amount: "100",
57-
});
176+
await alice.call(
177+
ft,
178+
"ft_transfer",
179+
{
180+
receiverId: root.accountId,
181+
amount: "100",
182+
},
183+
{ attachedDeposit: NEAR.from("1").toJSON() }
184+
);
58185
} catch (e) {
59186
t.assert(
60187
e
@@ -67,22 +194,30 @@ test("Cannot transfer if balance is not sufficient", async (t) => {
67194
});
68195

69196
test("Cross contract transfer", async (t) => {
70-
const { xcc, ft } = t.context.accounts;
71-
await ft.call(
197+
const { xcc, ft, root } = t.context.accounts;
198+
await xcc.call(
72199
ft,
73-
"ftTransferCall",
74-
{ receiverId: xcc.accountId, amount: "900", memo: null, msg: "test msg" },
75-
{ gas: 200000000000000 }
200+
"storage_deposit",
201+
{ account_id: xcc.accountId },
202+
{ attachedDeposit: NEAR.parse("1 N").toJSON() }
76203
);
77-
const aliBalance = await ft.view("ftBalanceOf", { accountId: xcc.accountId });
78-
t.is(aliBalance, "900");
79-
const aliSubContractData = await xcc.view("getContractData");
204+
await root.call(
205+
ft,
206+
"ft_transfer_call",
207+
{ receiver_id: xcc.accountId, amount: "900", memo: null, msg: "test msg" },
208+
{ gas: 200000000000000, attachedDeposit: NEAR.from("1").toJSON() }
209+
);
210+
const xccBalance = await ft.view("ft_balance_of", {
211+
account_id: xcc.accountId,
212+
});
213+
t.is(xccBalance, "900");
214+
const aliSubContractData = await xcc.view("get_contract_data");
80215
t.is(
81216
aliSubContractData,
82-
`[900 from ${ft.accountId} to ${xcc.accountId}] test msg `
217+
`[900 from ${root.accountId} to ${xcc.accountId}] test msg `
83218
);
84-
const ownerBalance = await ft.view("ftBalanceOf", {
85-
accountId: ft.accountId,
219+
const ownerBalance = await ft.view("ft_balance_of", {
220+
account_id: root.accountId,
86221
});
87222
t.is(ownerBalance, "100");
88223
});

‎examples/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
"build:counter-ts": "near-sdk-js build src/counter.ts build/counter-ts.wasm",
1515
"build:cross-contract-call": "near-sdk-js build src/status-message.js build/status-message.wasm && near-sdk-js build src/cross-contract-call.js build/cross-contract-call.wasm",
1616
"build:fungible-token-lockable": "near-sdk-js build src/fungible-token-lockable.js build/fungible-token-lockable.wasm",
17-
"build:fungible-token": "near-sdk-js build src/fungible-token.js build/fungible-token.wasm && near-sdk-js build src/fungible-token-helper.js build/fungible-token-helper.wasm",
17+
"build:fungible-token": "near-sdk-js build src/fungible-token.ts build/fungible-token.wasm && near-sdk-js build src/fungible-token-helper.ts build/fungible-token-helper.wasm",
1818
"build:non-fungible-token": "near-sdk-js build src/non-fungible-token-receiver.js build/non-fungible-token-receiver.wasm && near-sdk-js build src/non-fungible-token.js build/non-fungible-token.wasm",
1919
"build:status-message-collections": "near-sdk-js build src/status-message-collections.js build/status-message-collections.wasm",
2020
"build:parking-lot": "near-sdk-js build src/parking-lot.ts build/parking-lot.wasm",

‎examples/src/fungible-token-helper.js

-19
This file was deleted.

‎examples/src/fungible-token-helper.ts

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { NearBindgen, call, view } from "near-sdk-js";
2+
3+
@NearBindgen({})
4+
class _FungibleTokenHelper {
5+
data = "";
6+
7+
@call({})
8+
ft_on_transfer({
9+
sender_id,
10+
amount,
11+
msg,
12+
receiver_id,
13+
}: {
14+
sender_id: string;
15+
amount: string;
16+
msg: string;
17+
receiver_id: string;
18+
}) {
19+
const concatString = `[${amount} from ${sender_id} to ${receiver_id}] ${msg} `;
20+
this.data = this.data.concat("", concatString);
21+
}
22+
23+
@view({})
24+
get_contract_data() {
25+
return this.data;
26+
}
27+
}

0 commit comments

Comments
 (0)