Closed lansehuiyi6 closed 4 years ago
You can populate the abi cache with:
api.cachedAbis.set(contractName, {abi, rawAbi: null});
You need to serialize the action data before serializing that transaction. Easiest way is to use the transact method. To stop it from trying to use the rpc api, set api.chainId and populate the abi cache as above. Use transact's broadcast=false option and don't set its blocksBehind option.
broadcast
const { Api, JsonRpc } = require('eosjs'); const { JsSignatureProvider } = require('eosjs/dist/eosjs-jssig'); const fetch = require('fetch'); const { TextEncoder, TextDecoder } = require('text-encoding'); const privateKeys = ['************************']; const signatureProvider = new JsSignatureProvider(privateKeys);
let eosAbi = {"version": "eosio::abi/1.1", "types": [{"new_type_name": "time_t", "type": "uint32"} ], "structs": [{"name": "asset_t", "base": "", "fields": [{"name": "balance", "type": "asset"} ] }, {"name": "debt_t", "base": "", "fields": [{"name": "id", "type": "uint64"}, {"name": "pid", "type": "uint64"}, {"name": "npid", "type": "uint64"}, {"name": "quantity", "type": "asset"}, {"name": "lockedTime", "type": "time_t"}, {"name": "beginTime", "type": "time_point_sec"}, {"name": "status", "type": "string"}, {"name": "xHash", "type": "checksum256"} ] }, {"name": "fee_t", "base": "", "fields": [{"name": "fee", "type": "asset"} ] }, {"name": "inlock", "base": "", "fields": [{"name": "user", "type": "name"}, {"name": "htlc", "type": "name"}, {"name": "quantity", "type": "asset"}, {"name": "memo", "type": "string"} ] }, {"name": "inrdm", "base": "", "fields": [{"name": "htlc", "type": "name"}, {"name": "r", "type": "string"}, {"name": "s", "type": "string"}, {"name": "pk", "type": "string"}, {"name": "msg", "type": "string"}, {"name": "memo", "type": "string"} ] }, {"name": "inredeem", "base": "", "fields": [{"name": "storeman", "type": "name"}, {"name": "x", "type": "string"}, {"name": "r", "type": "string"}, {"name": "s", "type": "string"} ] }, {"name": "inrevoke", "base": "", "fields": [{"name": "user", "type": "name"}, {"name": "xHash", "type": "string"} ] }, {"name": "kk", "base": "", "fields": [{"name": "x", "type": "string"} ] }, {"name": "leftlocktime", "base": "", "fields": [{"name": "from", "type": "name"}, {"name": "table", "type": "name"}, {"name": "xHash", "type": "string"} ] }, {"name": "lkdebt", "base": "", "fields": [{"name": "htlc", "type": "name"}, {"name": "r", "type": "string"}, {"name": "s", "type": "string"}, {"name": "pk", "type": "string"}, {"name": "msg", "type": "string"}, {"name": "memo", "type": "string"} ] }, {"name": "lockdebt", "base": "", "fields": [{"name": "storeman", "type": "name"}, {"name": "quantity", "type": "asset"}, {"name": "npk", "type": "string"}, {"name": "xHash", "type": "string"}, {"name": "pk", "type": "string"}, {"name": "r", "type": "string"}, {"name": "s", "type": "string"} ] }, {"name": "outlk", "base": "", "fields": [{"name": "htlc", "type": "name"}, {"name": "r", "type": "string"}, {"name": "s", "type": "string"}, {"name": "pk", "type": "string"}, {"name": "msg", "type": "string"}, {"name": "memo", "type": "string"} ] }, {"name": "outlock", "base": "", "fields": [{"name": "storeman", "type": "name"}, {"name": "user", "type": "name"}, {"name": "quantity", "type": "asset"}, {"name": "xHash", "type": "string"}, {"name": "wanAddr", "type": "string"}, {"name": "pk", "type": "string"}, {"name": "r", "type": "string"}, {"name": "s", "type": "string"} ] }, {"name": "outredeem", "base": "", "fields": [{"name": "user", "type": "name"}, {"name": "x", "type": "string"} ] }, {"name": "outrevoke", "base": "", "fields": [{"name": "storeman", "type": "name"}, {"name": "xHash", "type": "string"}, {"name": "r", "type": "string"}, {"name": "s", "type": "string"} ] }, {"name": "outrvk", "base": "", "fields": [{"name": "htlc", "type": "name"}, {"name": "r", "type": "string"}, {"name": "s", "type": "string"}, {"name": "pk", "type": "string"}, {"name": "msg", "type": "string"}, {"name": "memo", "type": "string"} ] }, {"name": "pk_t", "base": "", "fields": [{"name": "id", "type": "uint64"}, {"name": "pkHash", "type": "checksum256"}, {"name": "pk", "type": "string"} ] }, {"name": "rdmdebt", "base": "", "fields": [{"name": "htlc", "type": "name"}, {"name": "r", "type": "string"}, {"name": "s", "type": "string"}, {"name": "pk", "type": "string"}, {"name": "msg", "type": "string"}, {"name": "memo", "type": "string"} ] }, {"name": "redeemdebt", "base": "", "fields": [{"name": "storeman", "type": "name"}, {"name": "x", "type": "string"}, {"name": "r", "type": "string"}, {"name": "s", "type": "string"} ] }, {"name": "regsig", "base": "", "fields": [{"name": "htlc", "type": "name"}, {"name": "code", "type": "name"}, {"name": "action", "type": "name"} ] }, {"name": "removepk", "base": "", "fields": [{"name": "storeman", "type": "name"}, {"name": "pk", "type": "string"}, {"name": "r", "type": "string"}, {"name": "s", "type": "string"} ] }, {"name": "revokedebt", "base": "", "fields": [{"name": "storeman", "type": "name"}, {"name": "xHash", "type": "string"}, {"name": "r", "type": "string"}, {"name": "s", "type": "string"} ] }, {"name": "rmpk", "base": "", "fields": [{"name": "htlc", "type": "name"}, {"name": "r", "type": "string"}, {"name": "s", "type": "string"}, {"name": "pk", "type": "string"}, {"name": "msg", "type": "string"}, {"name": "memo", "type": "string"} ] }, {"name": "rvkdebt", "base": "", "fields": [{"name": "htlc", "type": "name"}, {"name": "r", "type": "string"}, {"name": "s", "type": "string"}, {"name": "pk", "type": "string"}, {"name": "msg", "type": "string"}, {"name": "memo", "type": "string"} ] }, {"name": "signature_t", "base": "", "fields": [{"name": "code", "type": "name"}, {"name": "action", "type": "name"} ] }, {"name": "transfer_t", "base": "", "fields": [{"name": "id", "type": "uint64"}, {"name": "pid", "type": "uint64"}, {"name": "quantity", "type": "asset"}, {"name": "user", "type": "name"}, {"name": "lockedTime", "type": "time_t"}, {"name": "beginTime", "type": "time_point_sec"}, {"name": "status", "type": "string"}, {"name": "xHash", "type": "checksum256"}, {"name": "wanAddr", "type": "string"} ] }, {"name": "truncate", "base": "", "fields": [{"name": "table", "type": "name"}, {"name": "scope", "type": "string"} ] }, {"name": "unregsig", "base": "", "fields": [{"name": "htlc", "type": "name"}, {"name": "code", "type": "name"} ] }, {"name": "updatepk", "base": "", "fields": [{"name": "storeman", "type": "name"}, {"name": "npk", "type": "string"}, {"name": "pk", "type": "string"}, {"name": "r", "type": "string"}, {"name": "s", "type": "string"} ] }, {"name": "updatesig", "base": "", "fields": [{"name": "htlc", "type": "name"}, {"name": "code", "type": "name"}, {"name": "nCode", "type": "name"}, {"name": "nAction", "type": "name"} ] }, {"name": "updtpk", "base": "", "fields": [{"name": "htlc", "type": "name"}, {"name": "r", "type": "string"}, {"name": "s", "type": "string"}, {"name": "pk", "type": "string"}, {"name": "msg", "type": "string"}, {"name": "memo", "type": "string"} ] }, {"name": "wdr", "base": "", "fields": [{"name": "htlc", "type": "name"}, {"name": "r", "type": "string"}, {"name": "s", "type": "string"}, {"name": "pk", "type": "string"}, {"name": "msg", "type": "string"}, {"name": "memo", "type": "string"} ] }, {"name": "withdraw", "base": "", "fields": [{"name": "storeman", "type": "name"}, {"name": "sym", "type": "string"}, {"name": "pk", "type": "string"}, {"name": "r", "type": "string"}, {"name": "s", "type": "string"} ] } ], "actions": [{"name": "inlock", "type": "inlock", "ricardian_contract": ""}, {"name": "inrdm", "type": "inrdm", "ricardian_contract": ""}, {"name": "inredeem", "type": "inredeem", "ricardian_contract": ""}, {"name": "inrevoke", "type": "inrevoke", "ricardian_contract": ""}, {"name": "kk", "type": "kk", "ricardian_contract": ""}, {"name": "leftlocktime", "type": "leftlocktime", "ricardian_contract": ""}, {"name": "lkdebt", "type": "lkdebt", "ricardian_contract": ""}, {"name": "lockdebt", "type": "lockdebt", "ricardian_contract": ""}, {"name": "outlk", "type": "outlk", "ricardian_contract": ""}, {"name": "outlock", "type": "outlock", "ricardian_contract": ""}, {"name": "outredeem", "type": "outredeem", "ricardian_contract": ""}, {"name": "outrevoke", "type": "outrevoke", "ricardian_contract": ""}, {"name": "outrvk", "type": "outrvk", "ricardian_contract": ""}, {"name": "rdmdebt", "type": "rdmdebt", "ricardian_contract": ""}, {"name": "redeemdebt", "type": "redeemdebt", "ricardian_contract": ""}, {"name": "regsig", "type": "regsig", "ricardian_contract": ""}, {"name": "removepk", "type": "removepk", "ricardian_contract": ""}, {"name": "revokedebt", "type": "revokedebt", "ricardian_contract": ""}, {"name": "rmpk", "type": "rmpk", "ricardian_contract": ""}, {"name": "rvkdebt", "type": "rvkdebt", "ricardian_contract": ""}, {"name": "truncate", "type": "truncate", "ricardian_contract": ""}, {"name": "unregsig", "type": "unregsig", "ricardian_contract": ""}, {"name": "updatepk", "type": "updatepk", "ricardian_contract": ""}, {"name": "updatesig", "type": "updatesig", "ricardian_contract": ""}, {"name": "updtpk", "type": "updtpk", "ricardian_contract": ""}, {"name": "wdr", "type": "wdr", "ricardian_contract": ""}, {"name": "withdraw", "type": "withdraw", "ricardian_contract": ""} ], "tables": [{"name": "assets", "index_type": "i64", "key_names": [], "key_types": [], "type": "asset_t"}, {"name": "debts", "index_type": "i64", "key_names": [], "key_types": [], "type": "debt_t"}, {"name": "fees", "index_type": "i64", "key_names": [], "key_types": [], "type": "fee_t"}, {"name": "pks", "index_type": "i64", "key_names": [], "key_types": [], "type": "pk_t"}, {"name": "signer", "index_type": "i64", "key_names": [], "key_types": [], "type": "signature_t"}, {"name": "transfers", "index_type": "i64", "key_names": [], "key_types": [], "type": "transfer_t"} ], "ricardian_clauses": [], "error_messages": [], "abi_extensions": [], "variants": [] };
const rpc = new JsonRpc('', {fetch}); const api = new Api({ rpc, signatureProvider, textDecoder: new TextDecoder(), textEncoder: new TextEncoder() }); api.cachedAbis.set('eosio.token', {eosAbi, rawAbi:null});
async function sendTransaction() { try { let actions = [{ account: 'eosio.token', name: 'transfer', authorization: [{ actor: 'aaron', permission: 'active', }], data: { from: 'aaron', to: 'aaron1', quantity: '0.0001 EOS', memo: '', }, }];
let result = await api.transact({
actions: actions
}, {
// blocksBehind: 3,
// expireSeconds: 30,
broadcast: false,
// sign: false
});
console.log(result);
} catch (err) { console.log(err); } }
but i got the follow error:
{ TypeError: f is not a function
at JsonRpc.<anonymous> (/home/lizhan/wanglu/demo/js_shadow2/node_modules/eosjs/dist/eosjs-jsonrpc.js:99:46)
at step (/home/lizhan/wanglu/demo/js_shadow2/node_modules/eosjs/dist/eosjs-jsonrpc.js:36:23)
at Object.next (/home/lizhan/wanglu/demo/js_shadow2/node_modules/eosjs/dist/eosjs-jsonrpc.js:17:53)
at /home/lizhan/wanglu/demo/js_shadow2/node_modules/eosjs/dist/eosjs-jsonrpc.js:11:71
at new Promise (<anonymous>)
at __awaiter (/home/lizhan/wanglu/demo/js_shadow2/node_modules/eosjs/dist/eosjs-jsonrpc.js:7:12)
at JsonRpc.fetch (/home/lizhan/wanglu/demo/js_shadow2/node_modules/eosjs/dist/eosjs-jsonrpc.js:92:16)
at JsonRpc.<anonymous> (/home/lizhan/wanglu/demo/js_shadow2/node_modules/eosjs/dist/eosjs-jsonrpc.js:208:55)
at step (/home/lizhan/wanglu/demo/js_shadow2/node_modules/eosjs/dist/eosjs-jsonrpc.js:36:23)
at Object.next (/home/lizhan/wanglu/demo/js_shadow2/node_modules/eosjs/dist/eosjs-jsonrpc.js:17:53) isFetchError: true }
api.cachedAbis.set('eosio.token', {eosAbi, rawAbi:null});
This is missing the abi field. It doesn't expect a field named eosAbi.
Also, the abi you posted isn't eosio.token. It's a weird mangled mess from the sources of eosjs 16 that's not supported by 20.
The rpc object has a method to fetch the raw abi. You could save it in a file, but be careful since it's binary.
You should only need the binary if you're using jssig. Also, you didn't set api.chainId.
typo: you should not need the binary since you're using jssig.
typo: you should not need the binary since you're using jssig.
declare class JsSignatureProvider implements SignatureProvider {
/** map public to private keys */
keys: Map<string, ec.KeyPair>;
/** public keys */
availableKeys: string[];
/** @param privateKeys private keys to sign with */
constructor(privateKeys: string[]);
/** Public keys associated with the private keys that the `SignatureProvider` holds */
getAvailableKeys(): Promise<string[]>;
/** Sign a transaction */
sign({ chainId, requiredKeys, serializedTransaction, serializedContextFreeData }: SignatureProviderArgs): Promise<{
signatures: string[];
serializedTransaction: Uint8Array;
serializedContextFreeData: Uint8Array;
}>;
}
Refer to the above code about jssig, i only need chainid when i sign the serializedTransaction, yes? But before sign, chainid is needless?
typo: you should not need the binary since you're using jssig.
I've tried as you said.
const { Api, JsonRpc } = require('eosjs');
const { JsSignatureProvider } = require('eosjs/dist/eosjs-jssig');
const fetch = require('node-fetch');
const { TextEncoder, TextDecoder } = require('text-encoding');
let signatureProvider = new JsSignatureProvider(["*******************"]); // Your private key
async function get_rawabi_and_abi(account) {
try {
let endpoint = 'http://192.168.1.58:8888';
let rpc = new JsonRpc(endpoint, { fetch }) // EOS http endpoint
let api = new Api({ rpc, signatureProvider, textDecoder: new TextDecoder, textEncoder: new TextEncoder });
let rawAbi = (await api.abiProvider.getRawAbi(account)).abi;
let abi = (await api.abiProvider.get_abi(account)).abi;
console.log("==================get_rawabi_and_abi==================");
console.log(rawAbi);
console.log(abi);
let result = {
accountName: account,
rawAbi: rawAbi,
abi: abi
}
return result;
} catch (err) {
console.log(err);
}
}
async function main() {
try {
let result = await get_rawabi_and_abi('eosio.token');
console.log(result);
const rpc = new JsonRpc('http://should-never-be-called');
const api = new Api({ rpc, signatureProvider, textDecoder: new TextDecoder(), textEncoder: new TextEncoder() });
api.cachedAbis.set('eosio.token', {abi: result.abi, rawAbi:result.rawAbi});
let abi = (await api.rpc.get_abi('eosio.token')).abi;
console.log(abi);
} catch (err) {
console.log('err is', err);
}
}
main();
This time i use eosjs20 to get the abi and rawAbi first. I set the abi and rawabi, then i retry to get abi back. But i still get the error as follow, i don't know, i suspect there should be one bug during this. I even didn't try to do the transact action.
err is { TypeError: f is not a function
at JsonRpc.
Here's a solution. Not sure if you need the signing as well.
const { Api, JsonRpc } = require('eosjs');
const { JsSignatureProvider, PrivateKey } = require('eosjs/dist/eosjs-jssig');
const fetch = require('node-fetch');
const { TextEncoder, TextDecoder } = require('text-encoding');
const privateKeys = ['YOUR_PRIVATE_KEY']
const signatureProvider =
new JsSignatureProvider(privateKeys);
const get_rawabi_and_abi = async (account) => {
try {
const endpoint = 'http://localhost:8888';
const rpc = new JsonRpc(endpoint, { fetch });
const api = new Api({ rpc, signatureProvider, textDecoder: new TextDecoder, textEncoder: new TextEncoder });
const rawAbi = (await api.abiProvider.getRawAbi(account)).abi;
const abi = await api.rawAbiToJson(rawAbi);
const result = {
accountName: account,
rawAbi,
abi
};
return result;
} catch (err) {
console.log(err);
}
}
const main = async () => {
try {
const chainId = 'chain-id';
const abiObj = await get_rawabi_and_abi('eosio.token');
const rpc = new JsonRpc('http://should-never-be-called');
const api = new Api({ rpc, signatureProvider, textDecoder: new TextDecoder(), textEncoder: new TextEncoder(), chainId });
api.cachedAbis.set('eosio.token', {abi: abiObj.abi, rawAbi: abiObj.rawAbi});
const actions = [{
account: 'eosio.token',
name: 'transfer',
authorization: [{
actor: 'aaron',
permission: 'active',
}],
data: {
from: 'aaron',
to: 'aaron1',
quantity: '0.0001 EOS',
memo: '',
},
}];
const transaction = {
actions,
expiration: '2019-04-28T11:20:58',
ref_block_num: 26609,
ref_block_prefix: 934109041,
};
const result = await api.transact(transaction, { broadcast: false, sign: false });
const abis = await api.getTransactionAbis(transaction);
const requiredKeys = privateKeys.map((privateKey) => PrivateKey.fromString(privateKey).getPublicKey().toString());
result.signatures = await signatureProvider.sign({
chainId,
requiredKeys,
serializedTransaction: result.serializedTransaction,
serializedContextFreeData: result.serializedContextFreeData,
abis
});
console.log(result);
} catch (err) {
console.log('err is', err);
}
}
main()
Please let me know if the above code does not work.
Please let me know if the above code does not work.
Can I generate packed_trx from result.serializedTransaction ? Please help, we can do or not without "cleos convert pack_transaction" ?
eosjs-jsonrpc.ts
has a function called arrayToHex
that converts a serializedTransaction
to a packed_trx
. You can see how it's used in the push_transaction
method. Unfortunately it is not an exported function so you will need to copy it to your code to use it.
eosjs-jsonrpc.ts
has a function calledarrayToHex
that converts aserializedTransaction
to apacked_trx
. You can see how it's used in thepush_transaction
method. Unfortunately it is not an exported function so you will need to copy it to your code to use it.
Thanks let me try. Do you have Brave wallet ? if it work i want to bye your coffee.
Updated : It working.
const arrayToHex = (data) => {
let result = '';
for (const x of data) {
result += ('00' + x.toString(16)).slice(-2);
}; return result;
};
Version of EOSJS eosjs@20.0.2
Describe the bug How can i get the serializedTransaction without set the node url? If i want to do a colder wallet.
But i got the error: err is { TypeError: fetching abi for eosio.token: Only absolute URLs are supported at getNodeRequestOptions (/home/lizhan/wanglu/demo/js_shadow2/node_modules/node-fetch/lib/index.js:1299:9) at /home/lizhan/wanglu/demo/js_shadow2/node_modules/node-fetch/lib/index.js:1404:19 at new Promise ()
at fetch (/home/lizhan/wanglu/demo/js_shadow2/node_modules/node-fetch/lib/index.js:1401:9)
at JsonRpc. (/home/lizhan/wanglu/demo/js_shadow2/node_modules/eosjs/dist/eosjs-jsonrpc.js:99:46)
at step (/home/lizhan/wanglu/demo/js_shadow2/node_modules/eosjs/dist/eosjs-jsonrpc.js:36:23)
at Object.next (/home/lizhan/wanglu/demo/js_shadow2/node_modules/eosjs/dist/eosjs-jsonrpc.js:17:53)
at /home/lizhan/wanglu/demo/js_shadow2/node_modules/eosjs/dist/eosjs-jsonrpc.js:11:71
at new Promise ()
at __awaiter (/home/lizhan/wanglu/demo/js_shadow2/node_modules/eosjs/dist/eosjs-jsonrpc.js:7:12) isFetchError: true }
At version eosjs@16.0.9, i can get the serializedTransaction as follows:
Then i can get the sig with ecc.sign(sign_buf, pvt), but at version eosjs@20.0.2, how can i get a sign_buf before use the signProvider to sign?