1- import { Worker } from "near-workspaces" ;
1+ import { Worker , NEAR } from "near-workspaces" ;
22import test from "ava" ;
33
44test . 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
2727test . 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+
33137test ( "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
39143test ( "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
51167test ( "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
69196test ( "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} ) ;
0 commit comments