@cityofzion/neon-nep5
Version:
Neon-NEP5 Module
209 lines • 9.05 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getTokens = exports.getToken = exports.getTokenBalances = exports.getTokenBalance = void 0;
const neon_core_1 = require("@cityofzion/neon-core");
const abi = __importStar(require("./abi"));
const log = neon_core_1.logging.default("nep5");
/**
* Workaround for contracts such as SWTH returning Integer instead of ByteArray.
*/
function NumberParser(item) {
switch (item.type) {
case "Integer":
return new neon_core_1.u.Fixed8(item.value).div(100000000);
case "ByteArray":
return neon_core_1.u.Fixed8.fromReverseHex(item.value);
default:
throw new Error(`Received invalid type ${item.type}`);
}
}
const parseTokenInfo = neon_core_1.rpc.buildParser(neon_core_1.rpc.StringParser, neon_core_1.rpc.StringParser, neon_core_1.rpc.IntegerParser, NumberParser);
const parseTokenInfoAndBalance = neon_core_1.rpc.buildParser(neon_core_1.rpc.StringParser, neon_core_1.rpc.StringParser, neon_core_1.rpc.IntegerParser, NumberParser, NumberParser);
/**
* Get the balance of a single token for a single address.
* @param url Url of the NEO node to query.
* @param scriptHash ScriptHash of the NEP5 contract.
* @param address the Address to query for the balance.
*/
function getTokenBalance(url, scriptHash, address) {
return __awaiter(this, void 0, void 0, function* () {
const client = typeof url === "string" ? new neon_core_1.rpc.RPCClient(url) : url;
const sb = new neon_core_1.sc.ScriptBuilder();
abi.decimals(scriptHash)(sb);
abi.balanceOf(scriptHash, address)(sb);
const script = sb.str;
try {
const res = yield client.invokeScript(script);
const decimals = neon_core_1.rpc.IntegerParser(res.stack[0]);
return NumberParser(res.stack[1]).mul(Math.pow(10, 8 - decimals));
}
catch (err) {
log.error(`getTokenBalance failed with : ${err.message}`);
throw err;
}
});
}
exports.getTokenBalance = getTokenBalance;
/**
* Get token balances for an address.
* @param url URL of the NEO node to query.
* @param scriptHashArray Array of contract scriptHashes.
* @param address Address to query for balance of tokens.
*/
function getTokenBalances(url, scriptHashArray, address) {
return __awaiter(this, void 0, void 0, function* () {
const sb = new neon_core_1.sc.ScriptBuilder();
scriptHashArray.forEach((scriptHash) => {
abi.symbol(scriptHash)(sb);
abi.decimals(scriptHash)(sb);
abi.balanceOf(scriptHash, address)(sb);
});
const client = typeof url === "string" ? new neon_core_1.rpc.RPCClient(url) : url;
const res = yield client.invokeScript(sb.str);
const tokenList = {};
if (!res || !res.stack || res.stack.length !== 3 * scriptHashArray.length) {
throw new Error("Stack returned was invalid");
}
try {
for (let i = 0; i < res.stack.length; i += 3) {
try {
const symbol = neon_core_1.rpc.StringParser(res.stack[i]);
const decimals = neon_core_1.rpc.IntegerParser(res.stack[i + 1]);
tokenList[symbol] = NumberParser(res.stack[i + 2]).mul(Math.pow(10, 8 - decimals));
}
catch (e) {
log.error(`single call in getTokenBalances failed with : ${e.message}`);
throw e;
}
}
return tokenList;
}
catch (err) {
log.error(`getTokenBalances failed with : ${err.message}`);
throw err;
}
});
}
exports.getTokenBalances = getTokenBalances;
/**
* Retrieves the complete information about a token.
* @param url RPC Node url to query.
* @param scriptHash ScriptHash of the NEP5 contract.
* @param address Optional address to query the balance for. If provided, the returned object will include the balance property.
*/
function getToken(url, scriptHash, address) {
return __awaiter(this, void 0, void 0, function* () {
const parser = address ? parseTokenInfoAndBalance : parseTokenInfo;
const sb = new neon_core_1.sc.ScriptBuilder();
abi.name(scriptHash)(sb);
abi.symbol(scriptHash)(sb);
abi.decimals(scriptHash)(sb);
abi.totalSupply(scriptHash)(sb);
if (address) {
abi.balanceOf(scriptHash, address)(sb);
}
const script = sb.str;
try {
const client = typeof url === "string" ? new neon_core_1.rpc.RPCClient(url) : url;
const res = parser(yield client.invokeScript(script));
const result = {
name: res[0],
symbol: res[1],
decimals: res[2],
totalSupply: res[3].mul(Math.pow(10, 8 - res[2])).toNumber(),
};
if (address) {
result.balance = res[4].mul(Math.pow(10, 8 - res[2]));
}
return result;
}
catch (err) {
log.error(`getToken failed with : ${err.message}`);
throw err;
}
});
}
exports.getToken = getToken;
/**
* Retrieves the complete information about a list of tokens.
* @param url RPC Node url to query.
* @param scriptHashArray Array of NEP5 contract scriptHashes.
* @param address Optional address to query the balance for. If provided, the returned object will include the balance property.
*/
function getTokens(url, scriptHashArray, address) {
return __awaiter(this, void 0, void 0, function* () {
try {
const sb = new neon_core_1.sc.ScriptBuilder();
scriptHashArray.forEach((scriptHash) => {
abi.name(scriptHash)(sb);
abi.symbol(scriptHash)(sb);
abi.decimals(scriptHash)(sb);
abi.totalSupply(scriptHash)(sb);
if (address) {
abi.balanceOf(scriptHash, address)(sb);
}
});
const client = typeof url === "string" ? new neon_core_1.rpc.RPCClient(url) : url;
const res = yield client.invokeScript(sb.str);
const result = [];
const step = address ? 5 : 4;
for (let i = 0; i < res.stack.length; i += step) {
const name = neon_core_1.rpc.StringParser(res.stack[i]);
const symbol = neon_core_1.rpc.StringParser(res.stack[i + 1]);
const decimals = neon_core_1.rpc.IntegerParser(res.stack[i + 2]);
const totalSupply = NumberParser(res.stack[i + 3])
.mul(Math.pow(10, 8 - decimals))
.toNumber();
const balance = address
? NumberParser(res.stack[i + 4]).mul(Math.pow(10, 8 - decimals))
: undefined;
const obj = {
name,
symbol,
decimals,
totalSupply,
balance,
};
if (!obj.balance) {
delete obj.balance;
}
result.push(obj);
}
return result;
}
catch (err) {
log.error(`getTokens failed with : ${err.message}`);
throw err;
}
});
}
exports.getTokens = getTokens;
//# sourceMappingURL=main.js.map