-
Notifications
You must be signed in to change notification settings - Fork 70
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
Borsh #75
Borsh #75
Changes from all commits
ede0769
2c8240c
1666773
3c4eb63
1c4343b
3ad163a
c22afdb
55c4e38
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
import { Worker, BN } from 'near-workspaces'; | ||
import {readFile} from 'fs/promises' | ||
import test from 'ava'; | ||
|
||
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.before(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, | ||
'./node_modules/near-sdk-js/res/jsvm.wasm', | ||
); | ||
|
||
// Deploy status-message JS contract | ||
const statusMessage = await root.createSubAccount('status-message'); | ||
let contract_base64 = (await readFile('build/status-message-borsh.base64')).toString(); | ||
await statusMessage.call(jsvm, 'deploy_js_contract', Buffer.from(contract_base64, 'base64'), {attachedDeposit: '4000000000000000000000000', gas: '50 TGas'}); | ||
await statusMessage.call(jsvm, 'call_js_contract', encodeCall(statusMessage.accountId, 'init', []), {attachedDeposit: '400000000000000000000000', gas: '150 TGas'}); | ||
|
||
// Test users | ||
const ali = await root.createSubAccount('ali'); | ||
const bob = await root.createSubAccount('bob'); | ||
const carl = await root.createSubAccount('carl'); | ||
|
||
// Save state for test runs | ||
t.context.worker = worker; | ||
t.context.accounts = { root, jsvm, statusMessage, ali, bob, carl }; | ||
}); | ||
|
||
test.after(async t => { | ||
await t.context.worker.tearDown().catch(error => { | ||
console.log('Failed to tear down the worker:', error); | ||
}); | ||
}); | ||
|
||
test('Root gets null status', async t => { | ||
const { root, jsvm, statusMessage } = t.context.accounts; | ||
const result = await jsvm.view('view_js_contract', encodeCall(statusMessage.accountId, 'get_status', [root.accountId])); | ||
t.is(result, null); | ||
}); | ||
|
||
test('Ali sets then gets status', async t => { | ||
const { ali, jsvm, statusMessage } = t.context.accounts; | ||
await ali.call(jsvm, 'call_js_contract', encodeCall(statusMessage.accountId, 'set_status', ['hello']), {attachedDeposit: '100000000000000000000000', gas: '150 TGas'}); | ||
|
||
t.is( | ||
await jsvm.view('view_js_contract', encodeCall(statusMessage.accountId, 'get_status', [ali.accountId])), | ||
'hello' | ||
); | ||
}); | ||
|
||
test('Bob and Carl have different statuses', async t => { | ||
const {jsvm, statusMessage, bob, carl} = t.context.accounts; | ||
await bob.call(jsvm, 'call_js_contract', encodeCall(statusMessage.accountId, 'set_status', ['hello']), {attachedDeposit: '100000000000000000000000', gas: '150 TGas'}); | ||
await carl.call(jsvm, 'call_js_contract', encodeCall(statusMessage.accountId, 'set_status', ['world']), {attachedDeposit: '100000000000000000000000', gas: '150 TGas'}); | ||
|
||
const bobStatus = await jsvm.view('view_js_contract', encodeCall(statusMessage.accountId, 'get_status', [bob.accountId])); | ||
const carlStatus = await jsvm.view('view_js_contract', encodeCall(statusMessage.accountId, 'get_status', [carl.accountId])); | ||
t.is(bobStatus, 'hello'); | ||
t.is(carlStatus, 'world'); | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,15 +5,18 @@ | |
"main": "index.js", | ||
"type": "module", | ||
"scripts": { | ||
"build": "yarn build:simple && yarn build:collections", | ||
"build": "yarn build:simple && yarn build:collections && yarn build:borsh", | ||
"build:simple": "near-sdk build src/status-message.js build/status-message.base64", | ||
"build:collections": "near-sdk build src/status-message-collections.js build/status-message-collections.base64", | ||
"build:borsh": "near-sdk build src/status-message-borsh.js build/status-message-borsh.base64", | ||
"test": "ava" | ||
}, | ||
"author": "Near Inc <hello@nearprotocol.com>", | ||
"license": "Apache-2.0", | ||
"dependencies": { | ||
"near-sdk-js": "file:../../" | ||
"borsh": "https://github.com/near/borsh-js/tarball/import-buffer", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I do not understand how this branch is different and why are we using it here. Can we use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It has a |
||
"near-sdk-js": "file:../../", | ||
"yarn": "^1.22.19" | ||
}, | ||
"devDependencies": { | ||
"ava": "^4.2.0", | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
import { NearContract, NearBindgen, call, view, near } from 'near-sdk-js' | ||
import { serialize, deserialize } from 'borsh'; | ||
import { panic } from '../../../src/api'; | ||
import { Buffer } from 'buffer/' | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not the best practice. Can we add it as a dependency? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, should do so |
||
|
||
@NearBindgen | ||
class StatusMessage extends NearContract { | ||
constructor() { | ||
super() | ||
this.records = new Map() | ||
} | ||
|
||
deserialize() { | ||
borshDeserializeStatusMessage(this) | ||
} | ||
|
||
serialize() { | ||
borshSerializeStatusMessage(this) | ||
} | ||
|
||
@call | ||
set_status(message) { | ||
let account_id = near.signerAccountId() | ||
env.log(`${account_id} set_status with message ${message}`) | ||
this.records.set(account_id, message) | ||
} | ||
|
||
@view | ||
get_status(account_id) { | ||
env.log(`get_status for account_id ${account_id}`) | ||
return this.records.get(account_id) || null | ||
} | ||
} | ||
|
||
// This doesn't work, maybe due to @Nearbindgen cause this no longer the same class as StatusMessage | ||
// const schema = new Map([[StatusMessage, { | ||
// 'kind': 'struct', | ||
// 'fields': [ | ||
// ['records', {kind: 'map', key: 'string', value: 'string'}] | ||
// ] | ||
// }]]); | ||
|
||
class Assignable { | ||
constructor(properties) { | ||
Object.keys(properties).map((key) => { | ||
this[key] = properties[key]; | ||
}); | ||
} | ||
} | ||
|
||
class StatusMessageBorsh extends Assignable {} | ||
|
||
const schema = new Map([[StatusMessageBorsh, { | ||
'kind': 'struct', | ||
'fields': [ | ||
['records', {kind: 'map', key: 'string', value: 'string'}] | ||
] | ||
}]]); | ||
|
||
function borshSerializeStatusMessage(statusMessage) { | ||
let temp = new StatusMessageBorsh({records: statusMessage.records}) | ||
near.jsvmStorageWrite('STATE', serialize(schema, temp)); | ||
} | ||
|
||
function borshDeserializeStatusMessage(to) { | ||
let state = near.jsvmStorageRead('STATE'); | ||
|
||
if (state) { | ||
let temp = deserialize(schema, StatusMessageBorsh, Buffer.from(state)) | ||
Object.assign(to, temp); | ||
} else { | ||
throw new Error('Contract state is empty') | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note: Not sure why are we doing this change. Let's discuss it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
commonjs is used for import non-es packages, if I didn't remember it wrong, import commonjs module doesn't work without it.