@cityofzion/neon-api
Version:
Neon-API module: High level API for neon-js
117 lines • 4.73 kB
JavaScript
import { rpc, sc, u } from "@cityofzion/neon-core";
import { getTokenInfos } from "./api";
import { getCandidates } from "./api/getCandidates";
import { TransactionBuilder, TransactionValidator, ValidationAttributes, } from "./transaction";
export class NetworkFacade {
static async fromConfig(config) {
const i = new NetworkFacade(config);
await i.initialize();
return i;
}
constructor(config) {
this.magicNumber = 0;
this.client =
typeof config.node === "string"
? new rpc.NeoServerRpcClient(config.node)
: config.node;
}
async initialize() {
const response = await this.client.getVersion();
this.magicNumber = response.protocol.network;
}
getRpcNode() {
return this.client;
}
/**
* Constructs and executes a transaction of multiple token transfers
* @param intents - Token transfers
* @param config - Configuration
*/
async transferToken(intents, config) {
const client = this.getRpcNode();
const txBuilder = new TransactionBuilder();
for (const intent of intents) {
if (intent.decimalAmt) {
const [tokenInfo] = await getTokenInfos([intent.contractHash], client);
const amt = u.BigInteger.fromDecimal(intent.decimalAmt, tokenInfo.decimals);
txBuilder.addNep17Transfer(intent.from, intent.to, intent.contractHash, amt);
}
else if (intent.integerAmt) {
txBuilder.addNep17Transfer(intent.from, intent.to, intent.contractHash, intent.integerAmt);
}
else {
throw new Error("no amount specified!");
}
}
const txn = txBuilder.build();
const validateResult = await this.validate(txn);
if (!validateResult.valid) {
throw new Error("Unable to validate transaction");
}
const signedTxn = await this.sign(txn, config);
const sendResult = await this.getRpcNode().sendRawTransaction(signedTxn);
return sendResult;
}
/**
* Claims all the gas available for the specified account. Do note that GAS is automatically claimed when you perform a transaction involving NEO.
* @param acct - The account to claim gas on
* @param config - Configuration
*/
async claimGas(acct, config) {
const txn = TransactionBuilder.newBuilder().addGasClaim(acct).build();
const validateResult = await this.validate(txn);
if (!validateResult.valid) {
throw new Error("Unable to validate transaction");
}
const signedTxn = await this.sign(txn, config);
const sendResult = await this.getRpcNode().sendRawTransaction(signedTxn);
return sendResult;
}
/**
* Convenience method for getting list of candidates.
*/
async getCandidates() {
return getCandidates(this.getRpcNode());
}
async vote(acct, candidatePublicKey, config) {
const txn = TransactionBuilder.newBuilder()
.addVote(acct, candidatePublicKey)
.build();
const validateResult = await this.validate(txn);
if (!validateResult.valid) {
throw new Error("Unable to validate transaction");
}
const signedTxn = await this.sign(txn, config);
const sendResult = await this.getRpcNode().sendRawTransaction(signedTxn);
return sendResult;
}
/**
* Performs validation of all attributes on the given transaction.
* @param txn - Transaction to validate
*/
async validate(txn) {
const validator = new TransactionValidator(this.getRpcNode(), txn);
return await validator.validate(ValidationAttributes.All, ValidationAttributes.All);
}
/**
* Signs a transaction according to the signing configuration. The input transaction is modified with the signatures and returned.
* @param txn - Transaction to sign
* @param config - Configuration
* @returns
*/
async sign(txn, config) {
for (const [idx, w] of txn.witnesses.entries()) {
const signature = await config.signingCallback(txn, {
network: this.magicNumber,
witnessIndex: idx,
});
const invocationScript = new sc.OpToken(sc.OpCode.PUSHDATA1, signature).toScript();
w.invocationScript = u.HexString.fromHex(invocationScript);
}
return txn;
}
async invoke(contractCall) {
return this.getRpcNode().invokeFunction(contractCall.scriptHash, contractCall.operation, contractCall.args);
}
}
//# sourceMappingURL=NetworkFacade.js.map