Skip to content

Commit 63a5964

Browse files
authored
Merge pull request #21 from near/fungible-token
Fungible token example
2 parents ba8b04e + 12400ef commit 63a5964

File tree

12 files changed

+6717
-3
lines changed

12 files changed

+6717
-3
lines changed

examples/fungible-token/README.md

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# Fungible token contract in JavaScript
2+
3+
This is an equivalent JavaScript implementation of the fungible token example. Every user can send and recieve a fungible token.
4+
5+
## Build the contract
6+
7+
First ensure JSVM contract is build and deployed locally, follow [Local Installation](https://github.com/near/near-sdk-js#local-installation). Then run:
8+
```
9+
npm i
10+
npm run build
11+
```
12+
13+
## Test the contract with workspaces-js
14+
```
15+
npm run test
16+
```
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import { Worker } from 'near-workspaces';
2+
import {readFile} from 'fs/promises'
3+
import test from 'ava';
4+
5+
// TODO: make this function part of the npm package when it is available
6+
function encodeCall(contract, method, args) {
7+
return Buffer.concat([Buffer.from(contract), Buffer.from([0]), Buffer.from(method), Buffer.from([0]), Buffer.from(JSON.stringify(args))])
8+
}
9+
10+
test.beforeEach(async t => {
11+
// Init the worker and start a Sandbox server
12+
const worker = await Worker.init();
13+
14+
// Prepare sandbox for tests, create accounts, deploy contracts, etx.
15+
const root = worker.rootAccount;
16+
17+
// Deploy the jsvm contract.
18+
const jsvm = await root.createAndDeploy(
19+
root.getSubAccount('jsvm').accountId,
20+
'build/jsvm.wasm',
21+
);
22+
23+
// Deploy fungible token contract
24+
const fungibleTokenContract = await root.createSubAccount('fungible-token');
25+
let ftContractBase64 = (await readFile('build/fungible-token.base64')).toString();
26+
await fungibleTokenContract.call(jsvm, 'deploy_js_contract', Buffer.from(ftContractBase64, 'base64'), {attachedDeposit: '400000000000000000000000'});
27+
await fungibleTokenContract.call(jsvm, 'call_js_contract', encodeCall(fungibleTokenContract.accountId, 'init', ['a', '1000']), {attachedDeposit: '400000000000000000000000'});
28+
29+
// Create test accounts
30+
const ali = await root.createSubAccount('ali');
31+
const bob = await root.createSubAccount('bob');
32+
33+
// Save state for test runs, it is unique for each test
34+
t.context.worker = worker;
35+
t.context.accounts = {
36+
root,
37+
jsvm,
38+
fungibleTokenContract,
39+
ali,
40+
bob,
41+
};
42+
});
43+
44+
test.afterEach(async t => {
45+
await t.context.worker.tearDown().catch(error => {
46+
console.log('Failed tear down the worker:', error);
47+
});
48+
});
49+
50+
test('Owner has all balance in the beginning', async t => {
51+
const { jsvm, fungibleTokenContract } = t.context.accounts;
52+
const result = await jsvm.view('view_js_contract', encodeCall(fungibleTokenContract.accountId, 'ftBalanceOf', [fungibleTokenContract.accountId]));
53+
t.is(result, '1000');
54+
});
55+
56+
test('Can transfer if balance is sufficient', async t => {
57+
const { ali, jsvm, fungibleTokenContract } = t.context.accounts;
58+
59+
await fungibleTokenContract.call(jsvm, 'call_js_contract', encodeCall(fungibleTokenContract.accountId, 'ftTransfer', [ali.accountId, '100']), {attachedDeposit: '400000000000000000000000'});
60+
const aliBalance = await jsvm.view('view_js_contract', encodeCall(fungibleTokenContract.accountId, 'ftBalanceOf', [ali.accountId]));
61+
t.is(aliBalance, '100');
62+
const ownerBalance = await jsvm.view('view_js_contract', encodeCall(fungibleTokenContract.accountId, 'ftBalanceOf', [fungibleTokenContract.accountId]));
63+
t.is(ownerBalance, '900');
64+
});
65+
66+
test('Cannot transfer if balance is not sufficient', async t => {
67+
const { ali, bob, jsvm, fungibleTokenContract } = t.context.accounts;
68+
try {
69+
await ali.call(jsvm, 'call_js_contract', encodeCall(fungibleTokenContract.accountId, 'ftTransfer', [bob.accountId, '100']), {attachedDeposit: '400000000000000000000000'});
70+
} catch (e) {
71+
t.assert(e.toString().indexOf('Smart contract panicked: assertion failed: The account doesn\'t have enough balance') >= 0);
72+
}
73+
});
+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
require('util').inspect.defaultOptions.depth = 5; // Increase AVA's printing depth
2+
3+
module.exports = {
4+
timeout: '300000',
5+
files: ['**/*.ava.js'],
6+
failWithoutAssertions: false,
7+
extensions: ['js'],
8+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"plugins": [
3+
"../../sdk/near-bindgen-exporter",
4+
["@babel/plugin-proposal-decorators", {"version": "legacy"}]
5+
]
6+
}

examples/fungible-token/build.sh

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#!/bin/bash
2+
set -euo pipefail
3+
4+
mkdir -p build
5+
rollup -c
6+
cd build
7+
cp ../../../jsvm.wasm .
8+
../../../builder.sh fungible-token.js

0 commit comments

Comments
 (0)