Skip to content

Commit

Permalink
Merge pull request #21 from near/fungible-token
Browse files Browse the repository at this point in the history
Fungible token example
  • Loading branch information
ailisp committed May 18, 2022
2 parents ba8b04e + 12400ef commit 63a5964
Show file tree
Hide file tree
Showing 12 changed files with 6,717 additions and 3 deletions.
16 changes: 16 additions & 0 deletions examples/fungible-token/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Fungible token contract in JavaScript

This is an equivalent JavaScript implementation of the fungible token example. Every user can send and recieve a fungible token.

## Build the contract

First ensure JSVM contract is build and deployed locally, follow [Local Installation](https://github.com/near/near-sdk-js#local-installation). Then run:
```
npm i
npm run build
```

## Test the contract with workspaces-js
```
npm run test
```
73 changes: 73 additions & 0 deletions examples/fungible-token/__tests__/test-fungible-token.ava.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import { Worker } from 'near-workspaces';
import {readFile} from 'fs/promises'
import test from 'ava';

// TODO: make this function part of the npm package when it is available
function encodeCall(contract, method, args) {
return Buffer.concat([Buffer.from(contract), Buffer.from([0]), Buffer.from(method), Buffer.from([0]), Buffer.from(JSON.stringify(args))])
}

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 the jsvm contract.
const jsvm = await root.createAndDeploy(
root.getSubAccount('jsvm').accountId,
'build/jsvm.wasm',
);

// Deploy fungible token contract
const fungibleTokenContract = await root.createSubAccount('fungible-token');
let ftContractBase64 = (await readFile('build/fungible-token.base64')).toString();
await fungibleTokenContract.call(jsvm, 'deploy_js_contract', Buffer.from(ftContractBase64, 'base64'), {attachedDeposit: '400000000000000000000000'});
await fungibleTokenContract.call(jsvm, 'call_js_contract', encodeCall(fungibleTokenContract.accountId, 'init', ['a', '1000']), {attachedDeposit: '400000000000000000000000'});

// Create test accounts
const ali = await root.createSubAccount('ali');
const bob = await root.createSubAccount('bob');

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

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

test('Owner has all balance in the beginning', async t => {
const { jsvm, fungibleTokenContract } = t.context.accounts;
const result = await jsvm.view('view_js_contract', encodeCall(fungibleTokenContract.accountId, 'ftBalanceOf', [fungibleTokenContract.accountId]));
t.is(result, '1000');
});

test('Can transfer if balance is sufficient', async t => {
const { ali, jsvm, fungibleTokenContract } = t.context.accounts;

await fungibleTokenContract.call(jsvm, 'call_js_contract', encodeCall(fungibleTokenContract.accountId, 'ftTransfer', [ali.accountId, '100']), {attachedDeposit: '400000000000000000000000'});
const aliBalance = await jsvm.view('view_js_contract', encodeCall(fungibleTokenContract.accountId, 'ftBalanceOf', [ali.accountId]));
t.is(aliBalance, '100');
const ownerBalance = await jsvm.view('view_js_contract', encodeCall(fungibleTokenContract.accountId, 'ftBalanceOf', [fungibleTokenContract.accountId]));
t.is(ownerBalance, '900');
});

test('Cannot transfer if balance is not sufficient', async t => {
const { ali, bob, jsvm, fungibleTokenContract } = t.context.accounts;
try {
await ali.call(jsvm, 'call_js_contract', encodeCall(fungibleTokenContract.accountId, 'ftTransfer', [bob.accountId, '100']), {attachedDeposit: '400000000000000000000000'});
} catch (e) {
t.assert(e.toString().indexOf('Smart contract panicked: assertion failed: The account doesn\'t have enough balance') >= 0);
}
});
8 changes: 8 additions & 0 deletions examples/fungible-token/ava.config.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
require('util').inspect.defaultOptions.depth = 5; // Increase AVA's printing depth

module.exports = {
timeout: '300000',
files: ['**/*.ava.js'],
failWithoutAssertions: false,
extensions: ['js'],
};
6 changes: 6 additions & 0 deletions examples/fungible-token/babel.config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"plugins": [
"../../sdk/near-bindgen-exporter",
["@babel/plugin-proposal-decorators", {"version": "legacy"}]
]
}
8 changes: 8 additions & 0 deletions examples/fungible-token/build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#!/bin/bash
set -euo pipefail

mkdir -p build
rollup -c
cd build
cp ../../../jsvm.wasm .
../../../builder.sh fungible-token.js
Loading

0 comments on commit 63a5964

Please sign in to comment.