xyqon 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/cli.js +3 -1
- package/src/index.js +24 -11
package/package.json
CHANGED
package/src/cli.js
CHANGED
|
@@ -42,7 +42,7 @@ ${color('bold', 'Usage')}
|
|
|
42
42
|
xyqon wallet new --name <NAME> [--out <FILE>]
|
|
43
43
|
xyqon wallet show [--wallet <FILE>] [--private]
|
|
44
44
|
xyqon balance [--wallet <FILE>] [--address <PUBLIC_KEY>]
|
|
45
|
-
xyqon send --to <PUBLIC_KEY> --amount <AMOUNT> [--wallet <FILE>]
|
|
45
|
+
xyqon send --to <PUBLIC_KEY> --amount <AMOUNT> [--fee <AMOUNT>] [--wallet <FILE>]
|
|
46
46
|
xyqon coin create --symbol <SYMBOL> --name <NAME> --supply <AMOUNT> [--wallet <FILE>]
|
|
47
47
|
xyqon coin send --symbol <SYMBOL> --to <PUBLIC_KEY> --amount <AMOUNT> [--wallet <FILE>]
|
|
48
48
|
xyqon nft mint --collection <SYMBOL> --token-id <ID> --name <NAME> [--image-url <URL>] [--wallet <FILE>]
|
|
@@ -152,11 +152,13 @@ async function run() {
|
|
|
152
152
|
wallet,
|
|
153
153
|
recipient: options.to,
|
|
154
154
|
amount: options.amount,
|
|
155
|
+
fee: options.fee,
|
|
155
156
|
peers: peersFromOptions(options)
|
|
156
157
|
});
|
|
157
158
|
|
|
158
159
|
printHero('Transaction Sent');
|
|
159
160
|
console.log(`${color('bold', 'Amount:')} ${result.transaction.amount} XYQON`);
|
|
161
|
+
console.log(`${color('bold', 'Fee:')} ${result.transaction.fee} XYQON`);
|
|
160
162
|
console.log(`${color('bold', 'To:')} ${result.transaction.recipient}`);
|
|
161
163
|
console.log(`${color('bold', 'Transaction ID:')} ${result.transactionId}`);
|
|
162
164
|
console.log(`${color('dim', 'Checked balance:')} ${result.preflight.balance} XYQON at block ${result.preflight.blockHeight}`);
|
package/src/index.js
CHANGED
|
@@ -9,6 +9,7 @@ export const DEFAULT_PEERS = [
|
|
|
9
9
|
'147.182.138.183:7101'
|
|
10
10
|
];
|
|
11
11
|
const XYQON_EPSILON = 0.00000001;
|
|
12
|
+
export const DEFAULT_XYQON_TRANSACTION_FEE = 0.001;
|
|
12
13
|
|
|
13
14
|
export const DEFAULT_WALLET_PATH = 'xyqon.wallet.json';
|
|
14
15
|
|
|
@@ -103,8 +104,11 @@ function stringifyAssetOperationForSigning(assetOperation) {
|
|
|
103
104
|
throw new Error('unknown asset operation');
|
|
104
105
|
}
|
|
105
106
|
|
|
106
|
-
export function transactionPayload(sender, recipient, amount, senderPublicKey, assetOperation = null) {
|
|
107
|
-
|
|
107
|
+
export function transactionPayload(sender, recipient, amount, senderPublicKey, assetOperation = null, fee = 0) {
|
|
108
|
+
let base = `${sender}|${recipient}|${Number(amount).toFixed(8)}|${senderPublicKey}`;
|
|
109
|
+
if (Math.abs(Number(fee)) > XYQON_EPSILON) {
|
|
110
|
+
base = `${base}|fee:${Number(fee).toFixed(8)}`;
|
|
111
|
+
}
|
|
108
112
|
const serializedAsset = stringifyAssetOperationForSigning(assetOperation);
|
|
109
113
|
return serializedAsset ? `${base}|${serializedAsset}` : base;
|
|
110
114
|
}
|
|
@@ -174,22 +178,27 @@ export function normalizeTokenAmount(amount, label = 'amount') {
|
|
|
174
178
|
return numeric;
|
|
175
179
|
}
|
|
176
180
|
|
|
177
|
-
export function createSignedTransaction(wallet, recipient, amount) {
|
|
181
|
+
export function createSignedTransaction(wallet, recipient, amount, fee = DEFAULT_XYQON_TRANSACTION_FEE) {
|
|
178
182
|
const numericAmount = Number(amount);
|
|
179
183
|
if (!Number.isFinite(numericAmount) || numericAmount <= 0) {
|
|
180
184
|
throw new Error('amount must be a positive number');
|
|
181
185
|
}
|
|
186
|
+
const numericFee = Number(fee);
|
|
187
|
+
if (!Number.isFinite(numericFee) || numericFee < 0) {
|
|
188
|
+
throw new Error('fee must be a non-negative number');
|
|
189
|
+
}
|
|
182
190
|
|
|
183
191
|
const privateKey = hexToBytes(wallet.private_key);
|
|
184
192
|
const senderPublicKey = assertWalletMatchesPrivateKey(wallet, privateKey);
|
|
185
193
|
|
|
186
|
-
const payload = transactionPayload(wallet.name, recipient, numericAmount, senderPublicKey);
|
|
194
|
+
const payload = transactionPayload(wallet.name, recipient, numericAmount, senderPublicKey, null, numericFee);
|
|
187
195
|
const signature = ed25519.sign(new TextEncoder().encode(payload), privateKey);
|
|
188
196
|
|
|
189
197
|
return {
|
|
190
198
|
sender: wallet.name,
|
|
191
199
|
recipient,
|
|
192
200
|
amount: numericAmount,
|
|
201
|
+
fee: numericFee,
|
|
193
202
|
sender_public_key: senderPublicKey,
|
|
194
203
|
signature: bytesToHex(signature)
|
|
195
204
|
};
|
|
@@ -402,7 +411,7 @@ export function calculateBalances(chain) {
|
|
|
402
411
|
if (transaction.asset_operation) {
|
|
403
412
|
continue;
|
|
404
413
|
}
|
|
405
|
-
debit(transaction.sender_public_key, transaction.amount);
|
|
414
|
+
debit(transaction.sender_public_key, transaction.amount + (transaction.fee ?? 0));
|
|
406
415
|
credit(transaction.recipient, transaction.amount);
|
|
407
416
|
}
|
|
408
417
|
}
|
|
@@ -525,20 +534,24 @@ export async function getBalance(addressOrWallet, seedPeers = DEFAULT_PEERS) {
|
|
|
525
534
|
};
|
|
526
535
|
}
|
|
527
536
|
|
|
528
|
-
export async function assertSpendableXyqonBalance(wallet, amount, seedPeers = DEFAULT_PEERS) {
|
|
537
|
+
export async function assertSpendableXyqonBalance(wallet, amount, seedPeers = DEFAULT_PEERS, fee = 0) {
|
|
529
538
|
const numericAmount = Number(amount);
|
|
539
|
+
const numericFee = Number(fee);
|
|
530
540
|
const { chain, sourcePeer, peers } = await getBestChain(seedPeers);
|
|
531
541
|
const balances = calculateBalances(chain);
|
|
532
542
|
const balance = balances.get(wallet.public_key) ?? 0;
|
|
543
|
+
const totalDebit = numericAmount + numericFee;
|
|
533
544
|
|
|
534
|
-
if (balance + XYQON_EPSILON <
|
|
545
|
+
if (balance + XYQON_EPSILON < totalDebit) {
|
|
535
546
|
throw new Error(
|
|
536
|
-
`insufficient confirmed XYQON balance; balance is ${balance}, attempted to spend ${numericAmount}`
|
|
547
|
+
`insufficient confirmed XYQON balance; balance is ${balance}, attempted to spend ${numericAmount} plus fee ${numericFee}`
|
|
537
548
|
);
|
|
538
549
|
}
|
|
539
550
|
|
|
540
551
|
return {
|
|
541
552
|
balance,
|
|
553
|
+
fee: numericFee,
|
|
554
|
+
totalDebit,
|
|
542
555
|
blockHeight: chain.chain.at(-1)?.index ?? 0,
|
|
543
556
|
sourcePeer,
|
|
544
557
|
peers
|
|
@@ -624,9 +637,9 @@ export async function broadcastTransaction(transaction, seedPeers = DEFAULT_PEER
|
|
|
624
637
|
};
|
|
625
638
|
}
|
|
626
639
|
|
|
627
|
-
export async function sendTransaction({ wallet, recipient, amount, peers = DEFAULT_PEERS }) {
|
|
628
|
-
const transaction = createSignedTransaction(wallet, recipient, amount);
|
|
629
|
-
const preflight = await assertSpendableXyqonBalance(wallet, transaction.amount, peers);
|
|
640
|
+
export async function sendTransaction({ wallet, recipient, amount, fee = DEFAULT_XYQON_TRANSACTION_FEE, peers = DEFAULT_PEERS }) {
|
|
641
|
+
const transaction = createSignedTransaction(wallet, recipient, amount, fee);
|
|
642
|
+
const preflight = await assertSpendableXyqonBalance(wallet, transaction.amount, peers, transaction.fee);
|
|
630
643
|
return {
|
|
631
644
|
transaction,
|
|
632
645
|
preflight,
|