Add preliminary sendTokens() implementation

This commit is contained in:
Michael Vines
2018-08-24 17:14:58 -07:00
parent 1c365dc31c
commit 29148ef898
3 changed files with 169 additions and 43 deletions

View File

@ -5,6 +5,7 @@ import fetch from 'node-fetch';
import jayson from 'jayson/lib/client/browser';
import nacl from 'tweetnacl';
import {struct} from 'superstruct';
import bs58 from 'bs58';
import type {Account, PublicKey} from './account';
@ -229,19 +230,53 @@ export class Connection {
/**
* Send tokens to another account
*
* @todo THIS METHOD IS NOT FULLY IMPLEMENTED YET
* @ignore
*/
async sendTokens(from: Account, to: PublicKey, amount: number): Promise<TransactionSignature> {
const transaction = Buffer.from(
// TODO: This is not the correct transaction payload
`Transaction ${from.publicKey} ${to} ${amount}`
);
const lastId = await this.getLastId();
const fee = 0;
const signedTransaction = nacl.sign.detached(transaction, from.secretKey);
//
// TODO: Redo this...
//
const unsafeRes = await this._rpcRequest('sendTransaction', [[...signedTransaction]]);
// Build the transaction data to be signed.
const transactionData = Buffer.alloc(124);
transactionData.writeUInt32LE(amount, 4); // u64
transactionData.writeUInt32LE(amount - fee, 20); // u64
transactionData.writeUInt32LE(32, 28); // length of public key (u64)
{
const toBytes = Buffer.from(bs58.decode(to));
assert(toBytes.length === 32);
toBytes.copy(transactionData, 36);
}
transactionData.writeUInt32LE(32, 68); // length of last id (u64)
{
const lastIdBytes = Buffer.from(bs58.decode(lastId));
assert(lastIdBytes.length === 32);
lastIdBytes.copy(transactionData, 76);
}
// Sign it
const signature = nacl.sign.detached(transactionData, from.secretKey);
assert(signature.length === 64);
// Build the over-the-wire transaction buffer
const wireTransaction = Buffer.alloc(236);
wireTransaction.writeUInt32LE(64, 0); // signature length (u64)
Buffer.from(signature).copy(wireTransaction, 8);
wireTransaction.writeUInt32LE(32, 72); // public key length (u64)
{
const fromBytes = Buffer.from(bs58.decode(from.publicKey));
assert(fromBytes.length === 32);
fromBytes.copy(wireTransaction, 80);
}
transactionData.copy(wireTransaction, 112);
// Send it
const unsafeRes = await this._rpcRequest('sendTransaction', [[...wireTransaction]]);
const res = SendTokensRpcResult(unsafeRes);
if (res.error) {
throw new Error(res.error.message);
@ -251,4 +286,3 @@ export class Connection {
return res.result;
}
}