u3.js
v0.3.17
Published
A general library wrapped in javascript for interacting with Ultrain
Downloads
105
Readme
A general library wrapped in javascript for interacting with Ultrain.
中文文档看这里
Apply Environment
Browser(ES6)or NodeJS
If you want to integrate u3.js into a react native environment, there is a workable way to do this with rn-nodeify, see the example U3RNDemo
Usage
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>test</title>
<script src="../dist/u3.js"></script>
<script>
let func = async () => {
let u3 = U3.createU3({
httpEndpoint: "http://127.0.0.1:8888",
httpEndpointHistory: "http://127.0.0.1:3000"
});
await u3.getChainInfo();
const keyProvider = () => {
return ["5JbedY3jGfNK7HcLXcqGqSYrmX2n8wQWqZAuq6K7Gcf4Dj62UfL"];
};
const c = await u3.contract("utrio.token");
await c.transfer("ben", "bob", "1.0000 UGAS", "", { keyProvider });
};
func();
</script>
</head>
<body>
</body>
</html>
Installation
npm install u3.js
或 yarn add u3.js
Initialization
const { createU3 } = require('u3.js');
let config = {
httpEndpoint: "http://127.0.0.1:8888",
httpEndpointHistory: "http://127.0.0.1:3000",
chainId: "baf8bb9d3636379e3cd6779d2a72e693494670f1040d45154bb61dc8852c8971",
broadcast: true,
sign: true,
logger: {
directory: "../../logs", // daily rotate file directory
level: "info", // error->warn->info->verbose->debug->silly
console: true, // print to console
file: false // append to file
},
symbol: "UGAS",
//keyProvider:[],
//expireInSeconds:60
}
let u3 = createU3(config);
u3.getChainInfo((err, info) => {
if (err) {throw err;}
console.log(info);
});
Local environment running
Running u3 locally requires relying on docker.
1.Download docker from here and install it;
2.Then add the Chinese mirror address:https://registry.docker-cn.com;
3.Click on "Apply & Restart";
4.Go to u3.js/docker && ./start.sh
Configuration
Global configuration
- httpEndpoint string - http or https location of a ultrain providing a chain API. When using u3.js from a browser remember to configure the same origin policy in nodultrain or proxy server. For testing, nodultrain configuration access-control-allow-origin = * could be used.
- httpEndpointHistory string - http or https location of a ultrain providing a chain history API. When using u3.js from a browser remember to configure the same origin policy in nodultrain or proxy server. .
- chainId Unique ID for the blockchain you're connecting to. This is required for valid transaction signing. The chainId is provided via the get_chain_info API call.
- keyProvider [array|string|function] - Provides private keys used to sign transactions. If multiple private keys are found, the API get_required_keys is called to discover which signing keys to use. If a function is provided, this function is called for each transaction. If a keyProvider is not provided here, you should provided on a per-action or per-transaction basis in Options.
- expireInSeconds number - number of seconds before the transaction will expire. The time is based on the nodultrain's clock. An unexpired transaction that may have had an error is a liability until the expiration is reached, this time should be brief.
- broadcast [boolean=true] - post the transaction to the blockchain. Use false to obtain a fully signed transaction and it will not push to the blockchain.
- sign [boolean=true] - sign the transaction with a private key. Leaving a transaction unsigned avoids the need to provide a private key.
- logger - default logging configuration.
logger: {
directory: "../../logs", // daily rotate file directory
level: "info", // error->warn->info->verbose->debug->silly
console: true, // print to console
file: false // append to file
}
Options configuration
Options may be provided after parameters. Authorization is for individual actions.eg:
options = {
authorization: 'alice@active',
broadcast: true,
sign: true
}
u3.transfer('alice', 'bob', '1.0000 UGAS', '', options)
- authorization [array|auth] - identifies the signing account and permission typically in a multisig configuration. Authorization may be a string formatted as account@permission.
- broadcast [boolean=true] - post the transaction to the blockchain. Use false to obtain a fully signed transaction.
- sign [boolean=true] - sign the transaction with a private key. Leaving a transaction unsigned avoids the need to provide a private key.
- keyProvider [array|string|function] - just like the global keyProvider except this provides a temporary key for a single action or transaction.
await u3.anyAction('args', {keyProvider})
await u3.transaction(tr => { tr.anyAction() }, {keyProvider})
create Account
create accounts will need some staked tokens for RAM and bandwidth.
const u3 = createU3(config);
const name = 'abcdefg12345'; //common account should satisfy rule: Must be 12 bit in 12345abcdefghijklmnopqrstuvwxyz
let params = {
creator: 'ben',
name: name,
owner: pubkey,
active: pubkey,
updateable: 1,//[optional]whether the account can be updated( update contract)
};
await u3.createUser(params);
Transfer(UGAS)
transfer functions are used more frequently.
- transfer(from,to,content,memo) the content param should be using strict format with right decimal and symbol, eg '1.0000 UGAS'
const u3 = createU3(config);
const c = await u3.contract('utrio.token')
// with positional parameters
const result = await c.transfer('ben', 'bob', '1.2000 UGAS', '')
// or with named parameters
const result = await c.transfer({from: 'bob', to: 'ben', quantity: '1.3000 UGAS', memo: ''})
- If you want to confirm that the transfer logic has been really done, please follow these steps:
// first check whether the transaction was failed
if (!result || result.processed.receipt.status !== "executed") {
console.log("the transaction was failed");
return;
}
// then check whether the transaction was irreversible when it was not expired
let timeout = new Date(result.transaction.transaction.expiration + "Z") - new Date();
await U3Utils.test.waitUntil(async () => {
let tx = await u3.getTxByTxId(result.transaction_id);
return tx && tx.irreversible;
}, timeout, 1000);
Sign
send unsigned_transaction
Using { sign: false, broadcast: false }
to create a U3 instance and do some action.
And Then send the unsigned_transaction object to the ultrain-chain wallet.
Under these circumstances, you still need the network.
const u3_offline = createU3({ sign: false, broadcast: false });
const c = u3_offline.contract('utrio.token');
let unsigned_transaction = await c.transfer('ben', 'bob', '1 UGAS', 'test');
U3 will not initiate a network request if you set httpEndpoint
to null.
And you should pass in the transactionHeaders
parameters as below.
The abi
parameter is optional. when you ignore it, u3 will looking it from its local directory.
There are only two abis of 'ultrainio' and 'utrio.token' cached in local file.
Note that the max expiration
time is an hour (3600).
And you can fetch the ref_block_num
and ref_block_prefix
through u3.getBlockInfo
or the rest api http://xxx/v1/chain/get_block_info
const u3_offline = createU3({
sign: false,
broadcast: false,
httpEndpoint: null,
transactionHeaders: {
expiration: expiration.toISOString().split('.')[0],
ref_block_num: 5,
ref_block_prefix: 2950683920,
},
abi: JSON.parse('{"version":"ultraio:1.0","types":[{"new_type_name":"account_name","type":"name"}],"structs":[{"name":"transfer","base":"","fields":[{"name":"from","type":"account_name"},{"name":"to","type":"account_name"},{"name":"quantity","type":"asset"},{"name":"memo","type":"string"}]},{"name":"safe_transfer","base":"","fields":[{"name":"from","type":"account_name"},{"name":"to","type":"account_name"},{"name":"quantity","type":"asset"},{"name":"memo","type":"string"}]},{"name":"create","base":"","fields":[{"name":"issuer","type":"account_name"},{"name":"maximum_supply","type":"asset"}]},{"name":"issue","base":"","fields":[{"name":"to","type":"account_name"},{"name":"quantity","type":"asset"},{"name":"memo","type":"string"}]},{"name":"account","base":"","fields":[{"name":"balance","type":"asset"},{"name":"last_block_height","type":"uint32"}]},{"name":"currency_stats","base":"","fields":[{"name":"supply","type":"asset"},{"name":"max_supply","type":"asset"},{"name":"issuer","type":"account_name"}]}],"actions":[{"name":"transfer","type":"transfer","ricardian_contract":""},{"name":"safe_transfer","type":"safe_transfer","ricardian_contract":""},{"name":"issue","type":"issue","ricardian_contract":""},{"name":"create","type":"create","ricardian_contract":""}],"tables":[{"name":"accounts","type":"account","index_type":"i64","key_names":["currency"],"key_types":["uint64"]},{"name":"stat","type":"currency_stats","index_type":"i64","key_names":["currency"],"key_types":["uint64"]}],"ricardian_clauses":[],"abi_extensions":[]}'),
});
const c = u3_offline.contract('utrio.token');
let unsigned_transaction = await c.transfer('ben', 'bob', '1 UGAS', 'test');
Another example is createUser.
let expiration = new Date(new Date().getTime() + 60 * 1000);
const u3_offline = createU3({
httpEndpoint: null,
transactionHeaders: {
expiration: expiration.toISOString().split('.')[0],
ref_block_num: 5,
ref_block_prefix: 2950683920,
},
});
const name = randomName();
let params = {
creator: 'ben',
name: 'bob123',
owner: 'UTR6r...',
active: 'UTR6r...',
};
const unsigned_transaction = await u3_offline.createUser(params, {
sign: false,
broadcast: false,
authorization: [`ben@active`],
});
sign and push signed_transaction
In the wallet you can provide your privateKey or mnemonic to make a signature. And then push the signedTransaction to the ultrain-chain.
const u3_online = createU3();
let signature = await u3_online.sign(unsigned_transaction, privateKeyOrMnemonic, chainId);
if (signature) {
let signedTransaction = Object.assign({}, unsigned_transaction.transaction, { signatures: [signature] });
let processedTransaction = await u3_online.pushTx(signedTransaction);
}
Resource
Calling a contract will only spend the contract owner's resource. So if your want to deploy a contract, buy some resource before.
Please go to the developer website and choose the right resource package and make a purchase if you are in the MainNet environment, and go to the testnet explorer to do the self-service account recharge and resource purchase if you are in the TestNet environment.
- resourcelease(payer,receiver,slot,days,location)
const u3 = createU3(config);
const c = await u3.contract('ultrainio')
await c.resourcelease('ben', 'bob', 1, 10, "ultrainio");// 1 slot for 10 days on the side chain named ultrainio
And querying resource detail through the method below.
const account = await u3.getAccountInfo({ account_name: 'abcdefg12345' });
console.log(account.chain_resource[0].lease_num)
Contracts
deploy
Deploy and call smart contracts. Before you deploy the smart contract, you need to compile the typescript source files to webassembly targets, which are .abi,.wast,*.wasm.
- deploy(contracts_files_path, deploy_account) the contracts_files_path param is the absolute path of .abi,.wast,*.wasm. and the deploy_account is the one who will deploy the smart contract.
const u3 = createU3(config);
await u3.deploy(path.resolve(__dirname, '../contracts/token/token'), 'bob');
call actions
const u3 = createU3(config);
const tr = await u3.contract('ben');
await tr.transfer('bob', 'ben', '1.0000 UGAS','');
//or maybe like this
await u3.contract('ben').then(sm => sm.transfer('bob', 'ben', '1.0000 UGAS',''))
// Transaction with multiple contracts
await u3.transaction(['ben', 'bob'], ({sm1, sm2}) => {
sm1.myaction(..)
sm2.myaction(..)
})
custom Token
const u3 = createU3(config);
const account = 'bob';
await u3.transaction(account, token => {
token.create(account, '10000000.0000 DDD');
token.issue(account, '10000000.0000 DDD', 'issue');
});
const balance = await u3.getCurrencyBalance(account, account, 'DDD')
console.log('currency balance', balance)
Event
Ultrain provides an event registration and listening mechanism for asynchronous scenarios that trigger another action in the contract.The client needs to first register a listener address to the ultrain, then trigger the event via the emit method in the contract, and Ultrain will push the message to the registered listener address.
register/unregister
- registerEvent(deployer, listen_url)
- unregisterEvent(deployer, listen_url)
deployer : the account who deploy the contract
listen_url : the listening url which will receive the message
note: If you are testing in a docker envirnment, make sure the listening address is a local IP and can be access from docker.
const u3 = createU3(config);
const subscribe = await u3.registerEvent('ben', 'http://192.168.1.5:3002');
//or
const unsubscribe = await u3.unregisterEvent('ben', 'http://192.168.1.5:3002');
listen
const { createU3 listener } = require('u3.js');
listener(function(data) {
// do callback logic
console.log(data);
});
U3Utils.test.wait(2000);
//must call listener function before emit event
const contract = await u3.contract(account);
contract.hi('ben', 30, 'It is a test', { authorization: [`ben@active`] });