@zilliqa-js/account
Advanced tools
Comparing version 2.2.1 to 2.3.0-alpha.0
@@ -68,3 +68,31 @@ "use strict"; | ||
exports.formatOutgoingTx = function (req) { | ||
if (req.payload.method === core_1.RPCMethod.CreateTransaction && | ||
var e_1, _a; | ||
// if batch create transaction, payload is array | ||
if (Array.isArray(req.payload) && | ||
req.payload[0].method === core_1.RPCMethod.CreateTransaction && | ||
exports.isTxParams(req.payload[0].params[0])) { | ||
// loop thru batch payloads and format the params | ||
var payloads = []; | ||
try { | ||
for (var _b = tslib_1.__values(req.payload), _c = _b.next(); !_c.done; _c = _b.next()) { | ||
var txPayload = _c.value; | ||
var txConfig = txPayload.params[0]; | ||
payloads.push(tslib_1.__assign(tslib_1.__assign({}, txPayload), { params: [ | ||
tslib_1.__assign(tslib_1.__assign({}, txConfig), { amount: txConfig.amount.toString(), gasLimit: txConfig.gasLimit.toString(), gasPrice: txConfig.gasPrice.toString() }), | ||
] })); | ||
} | ||
} | ||
catch (e_1_1) { e_1 = { error: e_1_1 }; } | ||
finally { | ||
try { | ||
if (_c && !_c.done && (_a = _b.return)) _a.call(_b); | ||
} | ||
finally { if (e_1) throw e_1.error; } | ||
} | ||
var ret = tslib_1.__assign(tslib_1.__assign({}, req), { payload: payloads }); | ||
return ret; | ||
} | ||
// non-batch create transactions | ||
if (!Array.isArray(req.payload) && | ||
req.payload.method === core_1.RPCMethod.CreateTransaction && | ||
exports.isTxParams(req.payload.params[0])) { | ||
@@ -71,0 +99,0 @@ var txConfig = req.payload.params[0]; |
@@ -111,2 +111,3 @@ import { Signer, Provider } from '@zilliqa-js/core'; | ||
sign(tx: Transaction, offlineSign?: boolean): Promise<Transaction>; | ||
signBatch(txList: Transaction[]): Promise<Transaction[]>; | ||
/** | ||
@@ -113,0 +114,0 @@ * signWith |
@@ -223,2 +223,64 @@ "use strict"; | ||
}; | ||
Wallet.prototype.signBatch = function (txList) { | ||
return tslib_1.__awaiter(this, void 0, void 0, function () { | ||
var batchResults, signer_1, balance, nextNonce, _loop_1, this_1, index, err_1; | ||
return tslib_1.__generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
batchResults = []; | ||
if (!this.defaultAccount) { | ||
throw new Error('This wallet has no default account.'); | ||
} | ||
_a.label = 1; | ||
case 1: | ||
_a.trys.push([1, 7, , 8]); | ||
signer_1 = this.accounts[this.defaultAccount.address]; | ||
return [4 /*yield*/, this.provider.send('GetBalance', signer_1.address.replace('0x', '').toLowerCase())]; | ||
case 2: | ||
balance = _a.sent(); | ||
if (balance.result === undefined) { | ||
throw new Error('Could not get balance'); | ||
} | ||
if (typeof balance.result.nonce !== 'number') { | ||
throw new Error('Could not get nonce'); | ||
} | ||
nextNonce = balance.result.nonce + 1; | ||
_loop_1 = function (index) { | ||
var currentNonce, withNonceTx, signedTx; | ||
return tslib_1.__generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
currentNonce = index + nextNonce; | ||
withNonceTx = txList[index].map(function (txObj) { | ||
return tslib_1.__assign(tslib_1.__assign({}, txObj), { nonce: currentNonce, pubKey: signer_1.publicKey }); | ||
}); | ||
return [4 /*yield*/, this_1.sign(withNonceTx)]; | ||
case 1: | ||
signedTx = _a.sent(); | ||
batchResults.push(signedTx); | ||
return [2 /*return*/]; | ||
} | ||
}); | ||
}; | ||
this_1 = this; | ||
index = 0; | ||
_a.label = 3; | ||
case 3: | ||
if (!(index < txList.length)) return [3 /*break*/, 6]; | ||
return [5 /*yield**/, _loop_1(index)]; | ||
case 4: | ||
_a.sent(); | ||
_a.label = 5; | ||
case 5: | ||
index++; | ||
return [3 /*break*/, 3]; | ||
case 6: return [3 /*break*/, 8]; | ||
case 7: | ||
err_1 = _a.sent(); | ||
throw err_1; | ||
case 8: return [2 /*return*/, batchResults]; | ||
} | ||
}); | ||
}); | ||
}; | ||
/** | ||
@@ -234,3 +296,3 @@ * signWith | ||
return tslib_1.__awaiter(this, void 0, void 0, function () { | ||
var signer, gasPrice, gasLimit, debt, currNonce, balance, bal, withNonce_1, withPublicKey, err_1; | ||
var signer, gasPrice, gasLimit, debt, currNonce, balance, bal, withNonce_1, withPublicKey, err_2; | ||
return tslib_1.__generator(this, function (_a) { | ||
@@ -289,4 +351,4 @@ switch (_a.label) { | ||
case 5: | ||
err_1 = _a.sent(); | ||
throw err_1; | ||
err_2 = _a.sent(); | ||
throw err_2; | ||
case 6: return [2 /*return*/]; | ||
@@ -293,0 +355,0 @@ } |
{ | ||
"name": "@zilliqa-js/account", | ||
"version": "2.2.1", | ||
"version": "2.3.0-alpha.0", | ||
"author": "Ian Tan (https://github.com/iantanwx)", | ||
@@ -30,4 +30,4 @@ "maintainers": [ | ||
"@types/hdkey": "^0.7.0", | ||
"@zilliqa-js/core": "2.2.1", | ||
"@zilliqa-js/crypto": "2.2.1", | ||
"@zilliqa-js/core": "2.3.0-alpha.0", | ||
"@zilliqa-js/crypto": "2.3.0-alpha.0", | ||
"@zilliqa-js/proto": "2.2.0", | ||
@@ -41,3 +41,3 @@ "@zilliqa-js/util": "2.2.0", | ||
}, | ||
"gitHead": "cb55436aaed4f4ded30ccdfc747d5a4c8362563a" | ||
"gitHead": "d4f6f6e15d8b33da276e240dbfd85380bb9d397c" | ||
} |
@@ -258,2 +258,47 @@ # @zilliqa-js/account | ||
### `signBatch(txList: Transaction[]): Promise<Transaction[]>` | ||
Sign a list of `Transaction` with the default `Account`. This method is asynchronous | ||
as it will attempt to obtain the `nonce` from the `Provider`. | ||
**Parameters** | ||
- `txList`: `Transaction[]` - a list of `Transaction` instances. | ||
**Returns** | ||
- `Promise<Transaction[]>` - a list of signed transactions. | ||
**Example** | ||
```json | ||
// zilliqa, wallet obj declaration omitted for clarity | ||
let txList = []; | ||
for (let i = 0; i < 2; i++) { | ||
// create a new transaction object | ||
const tx = zilliqa.transactions.new( | ||
{ | ||
version: VERSION, | ||
toAddr: '0xA54E49719267E8312510D7b78598ceF16ff127CE', | ||
amount: new BN(units.toQa('1', units.Units.Zil)), | ||
gasPrice: units.toQa('2000', units.Units.Li), | ||
gasLimit: Long.fromNumber(1), | ||
}, | ||
false, | ||
); | ||
txList.push(tx); | ||
} | ||
// sign the batch transactions sequentially | ||
const batchResult = await zilliqa.wallet.signBatch(txList); | ||
for (const signedTx of batchResult) { | ||
// nonce must be different | ||
console.log('The signed transaction nonce is: %o', signedTx.nonce); | ||
console.log('The signed transaction signature is: %o\n', signedTx.signature); | ||
} | ||
``` | ||
## `Transaction` | ||
@@ -260,0 +305,0 @@ |
@@ -78,3 +78,36 @@ // Copyright (C) 2018 Zilliqa | ||
export const formatOutgoingTx: ReqMiddlewareFn<[TxParams]> = (req) => { | ||
// if batch create transaction, payload is array | ||
if ( | ||
Array.isArray(req.payload) && | ||
req.payload[0].method === RPCMethod.CreateTransaction && | ||
isTxParams(req.payload[0].params[0]) | ||
) { | ||
// loop thru batch payloads and format the params | ||
let payloads = []; | ||
for (const txPayload of req.payload) { | ||
const txConfig = txPayload.params[0]; | ||
payloads.push({ | ||
...txPayload, | ||
params: [ | ||
{ | ||
...txConfig, | ||
amount: txConfig.amount.toString(), | ||
gasLimit: txConfig.gasLimit.toString(), | ||
gasPrice: txConfig.gasPrice.toString(), | ||
}, | ||
], | ||
}); | ||
} | ||
const ret = { | ||
...req, | ||
payload: payloads, | ||
}; | ||
return ret; | ||
} | ||
// non-batch create transactions | ||
if ( | ||
!Array.isArray(req.payload) && | ||
req.payload.method === RPCMethod.CreateTransaction && | ||
@@ -81,0 +114,0 @@ isTxParams(req.payload.params[0]) |
@@ -242,2 +242,45 @@ // Copyright (C) 2018 Zilliqa | ||
async signBatch(txList: Transaction[]): Promise<Transaction[]> { | ||
let batchResults = []; | ||
if (!this.defaultAccount) { | ||
throw new Error('This wallet has no default account.'); | ||
} | ||
try { | ||
// nonce is assumed to come from default account | ||
const signer = this.accounts[this.defaultAccount.address]; | ||
const balance = await this.provider.send( | ||
'GetBalance', | ||
signer.address.replace('0x', '').toLowerCase(), | ||
); | ||
if (balance.result === undefined) { | ||
throw new Error('Could not get balance'); | ||
} | ||
if (typeof balance.result.nonce !== 'number') { | ||
throw new Error('Could not get nonce'); | ||
} | ||
let nextNonce = balance.result.nonce + 1; | ||
for (let index = 0; index < txList.length; index++) { | ||
// increment nonce for each new transaction | ||
const currentNonce = index + nextNonce; | ||
const withNonceTx = txList[index].map((txObj) => { | ||
return { | ||
...txObj, | ||
nonce: currentNonce, | ||
pubKey: signer.publicKey, | ||
}; | ||
}); | ||
const signedTx = await this.sign(withNonceTx); | ||
batchResults.push(signedTx); | ||
} | ||
} catch (err) { | ||
throw err; | ||
} | ||
return batchResults; | ||
} | ||
/** | ||
@@ -244,0 +287,0 @@ * signWith |
@@ -210,2 +210,102 @@ // Copyright (C) 2018 Zilliqa | ||
it('should sign batch transactions with default account', async () => { | ||
const [wallet] = createWallet(1); | ||
const pubKey = (wallet.defaultAccount && | ||
wallet.defaultAccount.publicKey) as string; | ||
let txList = []; | ||
for (let i = 0; i < 2; i++) { | ||
const tx = new Transaction( | ||
{ | ||
version: 1, | ||
toAddr: '0x1234567890123456789012345678901234567890', | ||
amount: new BN(0), | ||
gasPrice: new BN(1000), | ||
gasLimit: Long.fromNumber(1000), | ||
pubKey, | ||
}, | ||
provider, | ||
); | ||
txList.push(tx); | ||
} | ||
// first balance is for get balance before looping txlist | ||
// the other two balance is when it calls signWith | ||
// the last is for return value | ||
const responses = [ | ||
{ | ||
id: 1, | ||
jsonrpc: '2.0', | ||
result: { | ||
balance: '39999999000000000', | ||
nonce: 1, | ||
}, | ||
}, | ||
{ | ||
id: 1, | ||
jsonrpc: '2.0', | ||
result: { | ||
balance: '39999999000000000', | ||
nonce: 1, | ||
}, | ||
}, | ||
{ | ||
id: 1, | ||
jsonrpc: '2.0', | ||
result: { | ||
balance: '39999999000000000', | ||
nonce: 1, | ||
}, | ||
}, | ||
{ | ||
id: 1, | ||
jsonrpc: '2.0', | ||
result: { | ||
ID: 'some_hash', | ||
receipt: { success: true }, | ||
}, | ||
}, | ||
].map((res) => [JSON.stringify(res)] as [string]); | ||
fetch.mockResponses(...responses); | ||
const batchResult = await wallet.signBatch(txList); | ||
for (const signedTx of batchResult) { | ||
const signature = schnorr.toSignature(signedTx.txParams | ||
.signature as string); | ||
const lgtm = schnorr.verify( | ||
signedTx.bytes, | ||
signature, | ||
Buffer.from(pubKey, 'hex'), | ||
); | ||
expect(lgtm).toBeTruthy(); | ||
} | ||
}); | ||
it('should throw an error for sign batch with no default account', async () => { | ||
const pubKey = getPubKeyFromPrivateKey(schnorr.generatePrivateKey()); | ||
const [wallet] = createWallet(0); | ||
let txList: Transaction[] = []; | ||
for (let i = 0; i < 2; i++) { | ||
const tx = new Transaction( | ||
{ | ||
version: 1, | ||
toAddr: '0x1234567890123456789012345678901234567890', | ||
amount: new BN(0), | ||
gasPrice: new BN(1000), | ||
gasLimit: Long.fromNumber(1000), | ||
pubKey, | ||
}, | ||
provider, | ||
); | ||
txList.push(tx); | ||
} | ||
await expect(wallet.signBatch(txList)).rejects.toThrow( | ||
'This wallet has no default account.', | ||
); | ||
}); | ||
it('should throw an error if offline sign is true and txn does not have explicit nonce', async () => { | ||
@@ -212,0 +312,0 @@ const [wallet] = createWallet(1); |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
1448857
14562
513
2
+ Added@zilliqa-js/core@2.3.0-alpha.0(transitive)
+ Added@zilliqa-js/crypto@2.3.0-alpha.0(transitive)
- Removed@zilliqa-js/core@2.2.1(transitive)
- Removed@zilliqa-js/crypto@2.2.1(transitive)