@newcoin-foundation/newcoin-sdk
Version:
SDK for Newcoin blockchain
1,246 lines (1,043 loc) • 42.5 kB
text/typescript
// EOS imports
import { Api, JsonRpc, RpcError } from "eosjs";
import { Transaction, TransactResult } from "eosjs/dist/eosjs-api-interfaces";
import { JsSignatureProvider } from 'eosjs/dist/eosjs-jssig'; // development only
import { PushTransactionArgs } from "eosjs/dist/eosjs-rpc-interfaces";
const ecc = require("eosjs-ecc-priveos");
// Extra backend services
import { JsonRpc as HJsonRpc } from "@eoscafe/hyperion";
// Newcoin services
import { ActionGenerator as PoolsActionGenerator, RpcApi as PoolsRpcApi } from '@newcoin-foundation/newcoin.pools-js'
import { PoolPayload as PoolsPayload } from '@newcoin-foundation/newcoin.pools-js/dist/interfaces/pool.interface';
import { ActionGenerator as MainDAOActionGenerator } from '@newcoin-foundation/newcoin.pool-js';
import { ActionGenerator as DaosAG, ChainApi as DaosChainApi } from '@newcoin-foundation/newcoin.daos-js'
import { DAOPayload, GetTableRowsPayload, ProposalPayload } from "@newcoin-foundation/newcoin.daos-js/dist/interfaces";
import { ActionGenerator as sdkActionGen, EosioActionObject } from "./actions";
import fetch from 'cross-fetch';
import {
NCKeyPair,
NCCreateUser, NCCreateCollection,
NCCreatePool, NCStakePool, NCUnstakePool,
NCStakeMainDao, NCBuyRam,
NCCreateDao, NCGetDaoWhiteList,
NCCreateDaoProposal, NCCreateDaoUserWhitelistProposal, NCCreateDaoStakeProposal,
NCApproveDaoProposal, NCExecuteDaoProposal, NCGetVotes,
NCGetDaoProposals, NCDaoProposalVote, NCDaoWithdrawVoteDeposit,
NCMintAsset, NCCreatePermission,
NCGetAccInfo, NCGetPoolInfo, NCLinkPerm,
NCPoolsInfo, NCNameType,
NCReturnTxs, NCReturnInfo, NCTxBal, NCTxNcoBal, default_schema, SBT_NFT_schema
} from "./types";
export {
NCKeyPair,
NCCreateUser, NCCreateCollection,
NCCreatePool, NCStakePool, NCUnstakePool,
NCStakeMainDao,
NCCreateDao, NCGetDaoWhiteList, NCCreateDaoProposal, NCCreateDaoUserWhitelistProposal, NCCreateDaoStakeProposal,
NCApproveDaoProposal, NCExecuteDaoProposal, NCGetVotes, NCGetDaoProposals, NCDaoProposalVote,
NCMintAsset, NCCreatePermission,
NCGetAccInfo, NCGetPoolInfo, NCLinkPerm,
NCPoolsInfo, NCNameType,
NCReturnTxs, NCReturnInfo, NCTxBal, NCTxNcoBal, default_schema
};
import { normalizeUsername } from "./utils";
import { getClaimNftsActions, getClaimWinBidActions, getCreateAuctionActions, getEditAuctionActions, getEraseAuctionActions, getPlaceBidActions } from "./neftymarket";
import { NCClaimNftsParams, NCClaimWinBidParams, NCCreateAuctionParams, NCEditAuctionParams, NCEraseAuctionParams, NeftyMarketParamsBase, NCPlaceBidParams } from "./neftymarket/types";
const CREATE_ACCOUNT_DEFAULTS = {
ram_amt: 8192,
cpu_amount: '100.0000 NCO',
net_amount: '100.0000 NCO',
xfer: false,
};
export type NCInitUrls = {
nodeos_url: string,
hyperion_url: string,
atomicassets_url: string
};
export type NCInitServices = {
eosio_contract: string,
token_contract: string,
maindao_contract: string,
staking_contract: string,
daos_contract: string;
neftymarket_contract: string;
atomicassets_contract: string;
};
export const devnet_urls: NCInitUrls =
{
nodeos_url: "https://nodeos-dev.newcoin.org",
hyperion_url: "https://hyperion-dev.newcoin.org",
atomicassets_url: "https://atomic-dev.newcoin.org/"
};
export const devnet_services: NCInitServices =
{
eosio_contract: "eosio",
token_contract: "eosio.token",
maindao_contract: "pool.nco",
staking_contract: "pools2.nco",
daos_contract: "daos.nco",
neftymarket_contract: "market.nefty",
atomicassets_contract: "atomicassets"
};
/**
* The primary tool to interact with [https://newcoin.org](newcoin.org).
*
* This is an early alpha.
*
* See [https://docs.newcoin.org/](https://docs.newcoin.org/) for an overview of the newcoin ecosystem.
*/
export class NCO_BlockchainAPI {
private urls: NCInitUrls;
private services: NCInitServices;
//private aa_api: ExplorerApi;
private nodeos_rpc: JsonRpc;
private hrpc: HJsonRpc;
private poolsRpcApi: PoolsRpcApi;
// private poolRpcApi: PoolRpcApi;
private cApi: DaosChainApi;
private aGen: DaosAG;
private mGen: MainDAOActionGenerator;
private pGen: PoolsActionGenerator;
private sdkGen: sdkActionGen;
private debug: boolean = false;
static defaults = {
devnet_services,
devnet_urls,
default_schema
}
/**
* Init the api
* @name newcoin-api
* @param urls
* @param services
* @returns a Newcoin API instance
*/
constructor(
urls: NCInitUrls,
services: NCInitServices,
debug: boolean = false
) {
this.debug = debug;
this.urls = urls;
if(this.debug) console.log("Init URLS " + JSON.stringify(urls));
//this.aa_api = new ExplorerApi(this.urls.atomicassets_url, "atomicassets", { fetch: node_fetch });
this.nodeos_rpc = new JsonRpc(this.urls.nodeos_url, { fetch });
this.hrpc = new HJsonRpc(this.urls.hyperion_url, { fetch } as any);
this.cApi = new DaosChainApi(this.urls.nodeos_url, services.daos_contract, fetch);
this.poolsRpcApi = new PoolsRpcApi(this.urls.nodeos_url, services.staking_contract, fetch);
// this.poolRpcApi = new PoolRpcApi(this.urls.nodeos_url, services.maindao_contract, fetch)
this.aGen = new DaosAG(services.daos_contract, services.staking_contract);
this.mGen = new MainDAOActionGenerator(services.maindao_contract, services.token_contract);
this.pGen = new PoolsActionGenerator(services.staking_contract, services.maindao_contract);
this.sdkGen = new sdkActionGen(services.eosio_contract, services.token_contract);
this.services = services;
}
// Native EOS services
/**
* Create a key pair assuming a secure environment (not frontend)
* @params none
* @returns An EOS key pair
*/
async createKeyPair() {
await ecc.initialize();
let opts = { secureEnv: true };
let p = await ecc.randomKey(0, opts);
//let x = ecc.isValidPrivate(p);
let t: NCKeyPair = { prv_key: p, pub_key: ecc.privateToPublic(p) };
return t as NCKeyPair;
}
/**
* Create a user - multistage operation creating new user account,
* defailt collection, schema and template for the account
* @param NCCreateUser
* @returns NCReturnTxs
*/
async createUser(inpt: NCCreateUser) {
const {
newUser, newacc_pub_active_key, newacc_pub_owner_key,
payer, payer_prv_key,
ram_amt, net_amount, cpu_amount, xfer
} = { ...CREATE_ACCOUNT_DEFAULTS, ...inpt };
let res: NCReturnTxs = {};
let newacc_action = this.sdkGen.newaccount(newUser, payer, newacc_pub_active_key, newacc_pub_owner_key);
let buyram_action = this.sdkGen.buyrambytes(newUser, payer, ram_amt);
let delegatebw_action = this.sdkGen.delegateBw(newUser, payer, net_amount, cpu_amount, xfer);
if(this.debug) console.log("before create account transaction");
const tres = await this.SubmitTx(
[newacc_action, buyram_action, delegatebw_action],
[ecc.privateToPublic(payer_prv_key)],
[payer_prv_key]
) as TransactResult;// [] contained
res.TxID_createAcc = tres.transaction_id;
if(this.debug) console.log("createuser transaction complete");
return res;
}
async buyRam(inpt: NCBuyRam) {
let buyram_action = this.sdkGen.buyrambytes(inpt.user, inpt.payer, inpt.ram_amt);
const tres = await this.SubmitTx(
[buyram_action],
[ecc.privateToPublic(inpt.payer_prv_key)],
[inpt.payer_prv_key]
) as TransactResult;// [] contained
return { TxID_createAcc: tres.transaction_id } as NCReturnTxs;
}
/**
* Create default collection for the account
* @param NCCreateCollection
* @returns Create Collection and template transactions' ids
*/
async createCollection(inpt: NCCreateCollection) {
let t: any;
let res: NCReturnTxs = {};
let tres: TransactResult;
if (inpt.collection_name == undefined) inpt.collection_name = normalizeUsername(inpt.user, "z");
if (inpt.schema_name == undefined) inpt.schema_name = normalizeUsername(inpt.user, "w");
let sbt_sch_name = normalizeUsername(inpt.user, "s");
let user_public_active_key = ecc.privateToPublic(inpt.user_prv_active_key);
let mkt_fee = inpt.mkt_fee ? inpt.mkt_fee : 0.05;
let allow_notify = inpt.allow_notify ? inpt.allow_notify : true;
t = this.sdkGen.createCollection(
inpt.user,
inpt.collection_name,
[inpt.user],
[inpt.user],
mkt_fee,
allow_notify
);
if(this.debug) console.log(t);
if(this.debug) console.log("createcol transaction");
tres = await this.SubmitTx([t],
[user_public_active_key],
[inpt.user_prv_active_key]
) as TransactResult;
res.TxID_createCol = tres.transaction_id;
if(this.debug) console.log(tres);
if(this.debug) console.log("creating default schema ");
let schema_fields = inpt.schema_fields ? inpt.schema_fields : default_schema;
t = this.sdkGen.createSchema(
inpt.user,
inpt.collection_name, inpt.schema_name,
schema_fields);
if(this.debug) console.log(t);
if(this.debug) console.log("createsch transaction");
tres = await this.SubmitTx([t],
[user_public_active_key],
[inpt.user_prv_active_key]
) as TransactResult;
res.TxID_createSch = tres.transaction_id;
if(this.debug) console.log(tres);
if(this.debug) console.log("creating SBT schema");
let t1 = this.sdkGen.createSchema(
inpt.user,
inpt.collection_name, sbt_sch_name,
SBT_NFT_schema);
if(this.debug) console.log(t1);
if(this.debug) console.log("createsch SBT transaction");
tres = await this.SubmitTx([t1],
[user_public_active_key],
[inpt.user_prv_active_key]
) as TransactResult;
res.TxID_createSch = tres.transaction_id;
if(this.debug) console.log(tres);
if(this.debug) console.log("creating template");
let template = inpt.template_fields ? inpt.template_fields : [];
let xferable = inpt.xferable ? inpt.xferable : true;
let burnable = inpt.burnable ? inpt.burnable : true;
t = this.sdkGen.createTemplate(inpt.user, inpt.collection_name, inpt.schema_name, xferable, burnable, template);
if(this.debug) console.log(t);
if(this.debug) console.log("creating template transaction");
tres = await this.SubmitTx([t],
[user_public_active_key],
[inpt.user_prv_active_key]
) as TransactResult;
res.TxID_createTpl = res.TxID_createTpl;
if(this.debug) console.log(tres);
return res;
}
/**
* Create a new permission subordinate to the Active permission.
* (future optional: allow under owner, TBD)
* @param NCCreatePermission
* @returns Create permission transaction id
*/
async createPermission(inpt: NCCreatePermission) {
let t = this.sdkGen.createPermission(inpt.author, inpt.perm_name, inpt.perm_pub_key);
let res = await this.SubmitTx([t],
[ecc.privateToPublic(inpt.author_prv_active_key)],[inpt.author_prv_active_key]
) as TransactResult;
let r: NCReturnTxs = {};
r.TxID_createPerm = res.transaction_id;
return r;
}
/**
* Link a permission to a specific action of a specific contract.
* @param NCLinkPerm
* author: the permission's owner to be linked
* code: the owner of the action to be linked
* type: the action to be linked
* 'active', 'owner' ...
* @returns Link permission transaction id
*/
async linkPermission(inpt: NCLinkPerm) {
const linkauth_input = {
account: inpt.author, // this link
code: inpt.action_owner, //
type: inpt.action_to_link, //
requirement: inpt.perm_to_link, //
};
// the action which will make the linking
let action = {
account: 'eosio',
name: 'linkauth',
data: linkauth_input,
authorization: [{
actor: inpt.author,
permission: 'active'
}]
};
let res = await this.SubmitTx([action],
[ecc.privateToPublic(inpt.author_prv_active_key)],
[inpt.author_prv_active_key]
) as TransactResult;
let r: NCReturnTxs = {};
r.TxID_linkPerm = res.transaction_id;
return r;
}
/* =====================================================================================
* Main DAO service: common staking pool transfrming NCO (external convertible currency)
* into internal GNCO currency.
*
* Staked amount is subject to a staking fee, redemption delay and/or
* instant unstaking fee.
* @param NCStakeMainDao
* @returns NCReturnTxs
*/
async stakeMainDAO(inpt: NCStakeMainDao) {
let r: NCReturnTxs = {};
const stakeTx = await this.mGen.stake(
[{ actor: inpt.payer, permission: "active" }],
inpt.payer,
inpt.amt);
if(this.debug) console.log("action: " + JSON.stringify(stakeTx));
const res = await this.SubmitTx(stakeTx,
[ecc.privateToPublic(inpt.payer_prv_key)], [inpt.payer_prv_key]) as TransactResult;
r.TxID_stakeMainDAO = res.transaction_id;
return r;
}
/**
* Instant UnStake mainDAO with penalty
* @param NCStakeMainDao
* @returns NCReturnTxs
*/
async instUnstakeMainDAO(inpt: NCStakeMainDao) {
let r: NCReturnTxs = {};
const stakeTx = await this.mGen.instunstake(
[{ actor: inpt.payer, permission: "active" }],
inpt.payer,
inpt.amt);
if(this.debug) console.log("action: " + JSON.stringify(stakeTx));
const res = await this.SubmitTx(stakeTx,
[ecc.privateToPublic(inpt.payer_prv_key)],
[inpt.payer_prv_key]) as TransactResult;
r.TxID_unstakeMainDAO = res.transaction_id;
return r;
}
/**
* Delayed UnStake mainDAO delay without penalty
* @param NCStakeMainDao
* @returns NCReturnTxs
*/
async dldUnstakeMainDAO(inpt: NCStakeMainDao) {
let r: NCReturnTxs = {};
const stakeTx = await this.mGen.dldunstake(
[{ actor: inpt.payer, permission: "active" }],
inpt.payer,
inpt.amt);
if(this.debug) console.log("action: " + JSON.stringify(stakeTx));
const res = await this.SubmitTx(stakeTx,
[ecc.privateToPublic(inpt.payer_prv_key)],
[inpt.payer_prv_key]) as TransactResult;
r.TxID_unstakeMainDAO = res.transaction_id;
return r;
}
// ========================================================================
/** Staking pools service, issuing social tokens
*
* Create a staking pool for an account.
* Selection of ticker and inflation/deflation optionality
* @param NCCreatePool
* @returns Create Pool transaction id
*/
async createPool(inpt: NCCreatePool) {
inpt.ticker = (inpt.ticker || inpt.owner.substring(0, 5)).toUpperCase();
inpt.is_inflatable ??= true;
inpt.is_deflatable ??= true;
inpt.is_treasury ??= false;
if(this.debug) console.log("Creating pool: " + JSON.stringify(inpt));
let t = this.sdkGen.createPool(
inpt.owner,
inpt.ticker,
inpt.is_inflatable,
inpt.is_deflatable,
inpt.is_treasury,
"test pool for " + inpt.owner
);
let res = await this.SubmitTx([t],
[ecc.privateToPublic(inpt.owner_prv_active_key)], [inpt.owner_prv_active_key]
) as TransactResult;
let r: NCReturnTxs = {};
r.TxID_createPool = res.transaction_id;
return r;
}
/**
* Stake to creator pool
* @param
* @returns Create Pool transaction id
*/
async stakePool(inpt: NCStakePool) {
let p: PoolsPayload = { owner: inpt.owner };
let r: NCReturnTxs = {};
type RetT = { rows: PoolsPayload[] };
if(this.debug) console.log("Get poolbyowner: ", JSON.stringify(p));
let q = await this.poolsRpcApi.getPoolByOwner(p);
let t = await q.json() as RetT;
const pool_id = t.rows[0].id as string;
const pool_code = t.rows[0].code as string;
if(this.debug) console.log("pool:" + JSON.stringify(t));
const stakeTx = await this.pGen.stakeToPool(
[{ actor: inpt.payer, permission: "active" }],
inpt.payer, inpt.amt, pool_id);
if(this.debug) console.log("action: " + JSON.stringify(stakeTx));
const res = await this.SubmitTx(stakeTx,
[ecc.privateToPublic(inpt.payer_prv_key)],
[inpt.payer_prv_key]) as TransactResult;
r.TxID_stakePool = res.transaction_id;
r.pool_id = pool_id;
r.pool_code = pool_code;
return r;
}
// DAO functionality
/**
* Unstake creator pool
* @param NCUnstakePool
* @returns Create Pool transaction id
*/
async unstakePool(inpt: NCUnstakePool) {
const t = await this.pGen.withdrawFromPool(
[{ actor: inpt.payer, permission: "active" }], //{ actor: "io", permission: "active"}
inpt.payer,
inpt.amt);
if(this.debug) console.log("action: " + JSON.stringify(t));
const res = await this.SubmitTx(t,
[ecc.privateToPublic(inpt.payer_prv_key)],
[inpt.payer_prv_key]) as TransactResult;
let r: NCReturnTxs = {};
r.TxID_unstakePool = res.transaction_id;
return r;
}
/**
* DAO creation. One per account.
* @param inpt : NCCreateDao
* @returns NCReturnTxs.TxID_createDao, NCReturnTxs.dao_id
*/
async createDao(inpt: NCCreateDao) {
const t = await this.aGen.createDao(
[{ actor: inpt.author, permission: "active" }],
inpt.author,
inpt.descr
);
const res = await this.SubmitTx(t,
[ecc.privateToPublic(inpt.author_prv_key)], [inpt.author_prv_key]) as TransactResult;
let p: DAOPayload = { owner: inpt.author };
if(this.debug) console.log("Get dao by owner: ", JSON.stringify(p));
let q = await this.cApi.getDAOByOwner(p);
let w = await q.json();
if(this.debug) console.log("received from getDaoByOwner" + JSON.stringify(w));
let r: NCReturnTxs = {};
r.TxID_createDao = res.transaction_id;
r.dao_id = w.rows[0].id.toString();
// r.dao_id = r.dao_id.toString() ;
return r;
}
/**
*
* @param inpt : NCCreateDaoProposal
* @returns NCReturnTxs.TxID_createDaoProposal, NCReturnTxs.proposal_id
*/
async createDaoProposal(inpt: NCCreateDaoProposal) {
const dao_id = inpt.dao_id || (await this.getDaoIdByOwner(inpt.dao_owner));
const t = await this.aGen.createProposal(
[{ actor: inpt.proposer, permission: "active" }],
inpt.proposer, Number(dao_id),
inpt.title, inpt.summary,
inpt.url, inpt.vote_start, inpt.vote_end
);
const res = await this.SubmitTx(t,
[ecc.privateToPublic(inpt.proposer_prv_key)], [inpt.proposer_prv_key]) as TransactResult;
let r: NCReturnTxs = {};
r.TxID_createDaoProposal = res.transaction_id;
r.dao_id = dao_id;
const ps = await this.getDaoProposals({...inpt, dao_id }); // r.dao_id, inpt.proposer
r.proposal_id = ps.rows[ps.rows.length-1].id;
return r;
}
/**
*
* @param inpt : NCCreateDaoUserWhitelistProposal
* @returns NCReturnTxs.TxID_createDaoProposal, NCReturnTxs.proposal_id
*/
async createDaoUserWhitelistProposal(inpt: NCCreateDaoUserWhitelistProposal) {
const dao_id = inpt.dao_id || (await this.getDaoIdByOwner(inpt.dao_owner));
const t = await this.aGen.createWhiteListProposal(
[{ actor: inpt.proposer, permission: "active" }],
inpt.proposer, Number(dao_id), inpt.user,
inpt.vote_start, inpt.vote_end
);
const res = await this.SubmitTx(t,
[ecc.privateToPublic(inpt.proposer_prv_key)],
[inpt.proposer_prv_key]) as TransactResult;
let r: NCReturnTxs = {};
r.TxID_createDaoProposal = res.transaction_id;
r.dao_id = dao_id;
let ps = await this.getDaoWhitelistProposals(
{ dao_id: dao_id, proposal_author: inpt.proposer } as NCGetDaoProposals );
r.proposal_id = ps.rows[ps.rows.length - 1].id;
return r;
}
/**
*
* @param inpt : NCCreateDaoUserWhitelistProposal
* @returns NCReturnTxs.TxID_createDaoProposal, NCReturnTxs.proposal_id
*/
async createDaoStakeProposal(inpt: NCCreateDaoStakeProposal) {
const dao_id = inpt.dao_id || (await this.getDaoIdByOwner(inpt.dao_owner));
const t = await this.aGen.createStakeProposal(
[{ actor: inpt.proposer, permission: "active" }],
inpt.proposer, Number(dao_id),
inpt.to, inpt.quantity,
inpt.vote_start, inpt.vote_end
);
const res = await this.SubmitTx(t,
[ecc.privateToPublic(inpt.proposer_prv_key)],
[inpt.proposer_prv_key]) as TransactResult;
let r: NCReturnTxs = {};
r.TxID_createDaoProposal = res.transaction_id;
r.dao_id = dao_id;
let ps = await this.getDaoStakeProposals(
{ dao_id: dao_id, proposal_author: inpt.proposer } as NCGetDaoProposals );
r.proposal_id = ps.rows[ps.rows.length - 1].id;
return r;
}
/**
*
* @param inpt : NCApproveDaoProposal
* @returns NCReturnTxs.TxID_approveDaoProposal
*/
async approveDaoProposal(inpt: NCApproveDaoProposal) {
const dao_id = inpt.dao_id || (await this.getDaoIdByOwner(inpt.dao_owner));
if (inpt.proposal_id == undefined) throw ("Proposal undefined ID");
const t = await this.aGen.approveProposal(
[{ actor: inpt.approver, permission: "active" }],
Number(dao_id), inpt.proposal_id
);
const res = await this.SubmitTx(t,
[ecc.privateToPublic(inpt.approver_prv_key)], [inpt.approver_prv_key]) as TransactResult;
let r: NCReturnTxs = {};
r.TxID_approveDaoProposal = res.transaction_id;
return r;
}
/**
*
* @param inpt : NCApproveDaoProposal
* @returns NCReturnTxs.TxID_approveDaoProposal
*/
async approveDaoWhitelistProposal(inpt: NCApproveDaoProposal) {
const dao_id = inpt.dao_id || (await this.getDaoIdByOwner(inpt.dao_owner));
if (inpt.proposal_id == undefined) throw ("Proposal undefined ID");
const t = await this.aGen.approveWhiteListProposal(
[{ actor: inpt.approver, permission: "active" }],
Number(dao_id), inpt.proposal_id
);
const res = await this.SubmitTx(t,
[ecc.privateToPublic(inpt.approver_prv_key)], [inpt.approver_prv_key]) as TransactResult;
let r: NCReturnTxs = {};
r.TxID_approveDaoProposal = res.transaction_id;
return r;
}
/**
*
* @param inpt : NCExecuteDaoProposal
* @returns NCReturnTxs.TxID_executeDaoProposal
*/
async executeDaoProposal(inpt: NCExecuteDaoProposal) {
const dao_id = inpt.dao_id || (await this.getDaoIdByOwner(inpt.dao_owner));
if (inpt.proposal_id == undefined) throw ("Proposal ID undefined");
const t = await this.aGen.executeProposal(
[{ actor: inpt.exec, permission: "active" }],
Number(dao_id), inpt.proposal_id
);
const res = await this.SubmitTx(t,
[ecc.privateToPublic(inpt.exec_prv_key)], [inpt.exec_prv_key]) as TransactResult;
let r: NCReturnTxs = {};
r.TxID_executeDaoProposal = res.transaction_id;
return r;
}
/**
* @param inpt : NCExecuteDaoProposal
* @returns NCReturnTxs.TxID_executeDaoProposal
*/
async executeDaoWhitelistProposal(inpt: NCExecuteDaoProposal) {
const dao_id = inpt.dao_id || (await this.getDaoIdByOwner(inpt.dao_owner));
if (inpt.proposal_id == undefined) throw ("Proposal ID undefined");
const t = await this.aGen.executeWhiteListProposal(
[{ actor: inpt.exec, permission: "active" }], Number(dao_id), inpt.proposal_id
);
const res = await this.SubmitTx(t, [ecc.privateToPublic(inpt.exec_prv_key)], [inpt.exec_prv_key]) as TransactResult;
let r: NCReturnTxs = {};
r.TxID_executeDaoProposal = res.transaction_id;
return r;
}
/**
* @param inpt : NCCreateDao
* @returns NCReturnTxs.TxID_createDao, NCReturnTxs.dao_id
*/
async voteOnProposal(inpt: NCDaoProposalVote) {
const dao_id = inpt.dao_id || (await this.getDaoIdByOwner(inpt.dao_owner));
//if(this.debug) console.log("Vote for DAO proposal", JSON.stringify(inpt));
const t = await this.aGen.vote(
[{ actor: inpt.voter, permission: "active" }],
inpt.voter, inpt.quantity, inpt.proposal_type || "standart",
dao_id, inpt.proposal_id, inpt.option
);
if(this.debug) console.log("Vote for DAO proposal: ", JSON.stringify(t));
const res = await this.SubmitTx(t,
[ecc.privateToPublic(inpt.voter_prv_key)], [inpt.voter_prv_key]) as TransactResult;
//if(this.debug) console.log("received from VoteForDaoProposal" + JSON.stringify(res));
return { TxID_voteDaoProposal: res.transaction_id } as NCReturnTxs;
}
async withdrawVoteDeposit(inpt: NCDaoWithdrawVoteDeposit) {
//const dao_id = inpt.dao_id || (await this.getDaoIdByOwner(inpt.dao_owner));
if(this.debug) console.log("withdraw vote deposit make action", JSON.stringify(inpt));
const t = await this.aGen.withdraw(
[{ actor: inpt.voter, permission: "active" }],
inpt.voter, +inpt.vote_id
);
if(this.debug) console.log("Withdraw vote deposit send action: ", JSON.stringify(t));
const res = await this.SubmitTx(t,
[ecc.privateToPublic(inpt.voter_prv_key)], [inpt.voter_prv_key]) as TransactResult;
//if(this.debug) console.log("received from withdraw: " + JSON.stringify(res));
return { TxID_WithdrawVoteDeposit: res.transaction_id } as NCReturnTxs;
}
/**
* Mint an asset
* @param inpt: NCMintAsset
* @returns Create Pool transaction id
*/
async mintAsset(inpt: NCMintAsset) {
if (inpt.col_name == undefined) inpt.col_name = normalizeUsername(inpt.creator, "z");
if (inpt.sch_name == undefined) inpt.sch_name = normalizeUsername(inpt.creator, "w");
if (inpt.tmpl_id == undefined) inpt.tmpl_id = -1;
if (inpt.immutable_data == undefined)
inpt.immutable_data = [
{ key: 'name', value: ['string', inpt.creator + '_' + (new Date()).getTime()] }
];
if (inpt.mutable_data == undefined)
inpt.mutable_data = [];
const t = this.sdkGen.mintAsset(
inpt.creator, inpt.col_name, inpt.sch_name, inpt.tmpl_id,
inpt.immutable_data, inpt.mutable_data
);
let res = await this.SubmitTx([t],
[ecc.privateToPublic(inpt.payer_prv_key)],
[inpt.payer_prv_key]
) as TransactResult;
let r: NCReturnTxs = {};
r.TxID_mintAsset = res.transaction_id;
return r;
}
// Getters
/**
* @param inpt : NCCreateDao
* @returns NCReturnTxs.TxID_createDao, NCReturnTxs.dao_id
*/
async getDaoIdByOwner(owner?: string, noFail?: boolean) : Promise<string> {
if (!owner)
throw new Error("DAO undefined");
let p: DAOPayload = { owner: owner }
if(this.debug) console.log("Get dao by owner: ", JSON.stringify(p));
let q = await this.cApi.getDAOByOwner(p);
let w = await q.json();
if(this.debug) console.log("received from getDaoByOwner" + JSON.stringify(w));
if (!w.rows.length && !noFail)
throw new Error('User has no dao');
const r: string = w.rows[0]?.id?.toString();
if(!r && !noFail)
throw new Error("DAO undefined");
return r;
}
async getDaoProposals(inpt: NCGetDaoProposals) {
if(this.debug) console.log("Get proposal list: ", JSON.stringify(inpt));
const dao_id = inpt.dao_id || (await this.getDaoIdByOwner(inpt.dao_owner, true));
if(!dao_id) return { dao_id: null };
let w;
if(inpt.proposal_author || inpt.proposal_id) {
w = await (await this.cApi.getProposalByProposer({ ...inpt, daoID: dao_id })).json();
} else {
const opt = {
json: true,
code: "daos.nco",
scope: dao_id,
table: "proposals",
lower_bound: inpt.lower_bound,
upper_bound: inpt.upper_bound,
limit: ~~(inpt.limit??"10"),
reverse: inpt.reverse,
index_position: "1",
} as GetTableRowsPayload;
w = await (await this.cApi.getTableRows( opt )).json();
}
if(this.debug) console.log("received proposal list" + JSON.stringify(w));
return { ...w, dao_id };
}
async getDaoWhitelistProposals(inpt: NCGetDaoProposals) {
if(this.debug) console.log("Get proposal list: ", JSON.stringify(inpt));
const dao_id = inpt.dao_id || (await this.getDaoIdByOwner(inpt.dao_owner, true));
if(!dao_id) return { dao_id: null };
let w;
if(inpt.proposal_author || inpt.proposal_id) {
w = await (await this.cApi.getWhiteListProposalByProposer({ ...inpt, daoID: dao_id })).json();
} else {
const opt = {
json: true,
code: "daos.nco",
scope: dao_id,
table: "whlistprpls",
lower_bound: inpt.lower_bound,
upper_bound: inpt.upper_bound,
limit: ~~(inpt.limit??"10"),
reverse: inpt.reverse,
index_position: "1",
} as GetTableRowsPayload;
w = await (await this.cApi.getTableRows( opt )).json();
}
if(this.debug) console.log("received proposal list" + JSON.stringify(w));
return { ...w, dao_id };
}
async getDaoStakeProposals(inpt: NCGetDaoProposals) {
if(this.debug) console.log("Get proposal list: ", JSON.stringify(inpt));
const dao_id = inpt.dao_id || (await this.getDaoIdByOwner(inpt.dao_owner, true));
if(!dao_id) return { dao_id: null };
let w;
if(inpt.proposal_author || inpt.proposal_id) {
w = await (await this.cApi.getStakeProposalByProposer({ ...inpt, daoID: dao_id })).json();
} else {
const opt = {
json: true,
code: "daos.nco",
scope: dao_id,
table: "stakeprpls",
lower_bound: inpt.lower_bound,
upper_bound: inpt.upper_bound,
limit: ~~(inpt.limit??"10"),
reverse: inpt.reverse,
index_position: "1",
} as GetTableRowsPayload;
w = await (await this.cApi.getTableRows( opt )).json();
}
if(this.debug) console.log("received proposal list" + JSON.stringify(w));
return { ...w, dao_id };
}
async getDaoProposal(inpt: NCGetDaoProposals) {
const dao_id = inpt.dao_id || (await this.getDaoIdByOwner(inpt.dao_owner));
if(!inpt.proposal_id) throw "Must provide proposal ID";
let w = await (await this.cApi.getProposalByID({ daoID: inpt.dao_id as string, id: inpt.proposal_id })).json();
if(this.debug) console.log("received from getProposalByID " + JSON.stringify(w.rows[0]));
return { ...w, dao_id };
}
async getDaoWhitelistProposal(inpt: NCGetDaoProposals) {
const dao_id = inpt.dao_id || (await this.getDaoIdByOwner(inpt.dao_owner));
if (!inpt.proposal_id) throw "Must provide proposal ID";
let w = await (await this.cApi.getWhiteListProposal({ daoID: dao_id, id: inpt.proposal_id })).json();
if(this.debug) console.log("received from getProposalByID" + JSON.stringify(w.rows[0]));
return { ...w, dao_id: inpt.dao_id };
}
async listDaoProposals(inpt: NCGetDaoProposals) {
const dao_id = inpt.dao_id || (await this.getDaoIdByOwner(inpt.dao_owner));
let opt: ProposalPayload = { daoID: dao_id};
//opt.proposer = inpt.proposal_author ?? undefined;
if(this.debug) console.log("sent to getProposalByProposer: " + JSON.stringify(opt));
let q = await this.cApi.getProposalByProposer(opt);
if(this.debug) console.log("received from getProposalByProposer: " + JSON.stringify(q));
let w = (await q.json()).rows;
return { list: w, id: dao_id };
}
async listDaoWhitelistProposals(inpt: NCGetDaoProposals) {
const dao_id = inpt.dao_id || (await this.getDaoIdByOwner(inpt.dao_owner));
let opt: ProposalPayload = { daoID: dao_id};
//opt.proposer = inpt.proposal_author ?? undefined;
let q = await this.cApi.getWhiteListProposalByProposer(opt);
if(this.debug) console.log("received from getProposalByProposer: " + JSON.stringify(q));
let w = (await q.json()).rows;
if(this.debug) console.log("received from getProposalByProposer: " + JSON.stringify(w));
return { list: w, id: dao_id };
}
async getDaoWhitelist(inpt: NCGetDaoWhiteList) {
const dao_id = inpt.dao_id || (await this.getDaoIdByOwner(inpt.dao_owner));
//let q = await this.cApi.getDAOWhiteList({ id: inpt.dao_id as string });
//let w = await q.json();
const opt = {
json: true,
code: "daos.nco",
scope: dao_id,
table: "whitelist",
key_type: "name",
lower_bound: inpt.lower_bound,
upper_bound: inpt.upper_bound,
limit: ~~(inpt.limit??"10"),
reverse: inpt.reverse,
index_position: "1",
} as GetTableRowsPayload;
let w = await (await this.cApi.getTableRows( opt )).json();
if(this.debug) console.log("received white list" + JSON.stringify(w));
return { ...w, dao_id };
}
async getVotes(inpt: NCGetVotes) {
let w;
const opt = {
json: true,
code: "daos.nco",
scope: inpt.voter,
table: "votes",
key_type: "i64",
lower_bound: inpt.lower_bound,
upper_bound: inpt.upper_bound,
limit: ~~(inpt.limit??"10"),
reverse: inpt.reverse,
index_position: "1",
} as GetTableRowsPayload;
w = await (await this.cApi.getTableRows(opt)).json();
if(this.debug) console.log("received from getVotes " + JSON.stringify(w.rows));
return w;
}
/**
* Get account balance
* @param acc: NCGetAccInfo
* @param acc.token_name will set correct contract
* @returns Tx data
*/
async getAccountBalance(acc: NCGetAccInfo) {
if (!acc.contract) {
if (acc.token_name == "GNCO")
acc.contract = this.services.maindao_contract;
else
if (acc.token_name != "NCO")
acc.contract = this.services.staking_contract;
else
acc.contract = this.services.eosio_contract;
}
let rc: NCReturnInfo = { acc_balances: [] };
try {
let t = await fetch(`https://nodeos-dev.newcoin.org/v1/chain/get_currency_balance`, { // TODO
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
account: acc.owner,
code: acc.contract
}),
});
rc.acc_balances = await t.json();
//if(this.debug) if(this.debug) console.log(rc);
return rc;
} catch (e) {
if(this.debug) console.log('\nCaught exception: ' + e);
if (e instanceof RpcError && this.debug) console.log(JSON.stringify(e.json, null, 2));
throw e;
}
}
/**
* Transfer GNCO between accounts
* @param NCTxBal
* @returns Transfer transaction id
*/
async txGNCOBalance(inpt: NCTxBal) {
const r = await this._txBalance(this.services.maindao_contract, inpt);
return r;
}
/**
* Transfer NCO between accounts
* @param NCTxBal
* @returns Transfer transaction id
*/
async txNCOBalance(inpt: NCTxBal) {
const r = await this._txBalance(this.services.token_contract, inpt);
return r;
}
/**
* Transfer creator tokens between accounts
* @param NCTxBal
* @returns Transfer transaction id
*/
async txDAOTokenBalance(inpt: NCTxBal) {
const r = await this._txBalance(this.services.staking_contract, inpt);
return r;
}
/**
* Get pool info
* @param
* @returns Tx data
*/
async getPoolInfo(payload: NCGetPoolInfo) {
const api = new PoolsRpcApi("https://nodeos-dev.newcoin.org", "pools2.nco", fetch); // TODO
try {
const fn = payload.code ? "getPoolByCode" : "getPoolByOwner";
let q = await api[fn](payload);
let t = await q.json() as NCPoolsInfo;
return t;
} catch (e) {
if(this.debug) console.log('\nCaught exception: ' + e);
if (e instanceof RpcError)
if(this.debug) console.log(JSON.stringify(e.json, null, 2));
}
return {} as NCPoolsInfo;
``
}
/**
* Get trasaction data
* @returns Tx data
*/
async getTxData(txid: string) {
let txi = await this.hrpc.get_transaction(txid);
if(this.debug) console.log(txi); // get template number txi.actions[1].act.data.template_id
return txi;
}
// AUX functions
/**
* Transfer NCO between accounts
* @returns Transfer transaction id
*/
async _txBalance(contract: string, inpt: NCTxBal): Promise<NCReturnTxs> {
let r: NCReturnTxs = {};
let tx = this.sdkGen.txBalance(contract, inpt.payer, inpt.to, inpt.amt, inpt.memo ??= "");
let res = await this.SubmitTx([tx],
[ecc.privateToPublic(inpt.payer_prv_key)],
[inpt.payer_prv_key]
) as TransactResult;
r.TxID = res.transaction_id;
return r;
}
// Neftymarket
private getActionParams<T>(params: T): NeftyMarketParamsBase & T {
return {
atomicassetsContract: this.services.atomicassets_contract,
neftymarketContract: this.services.neftymarket_contract,
...params,
};
}
private async submitAuctionTx(actions: EosioActionObject[], payer_prv_key: string): Promise<NCReturnTxs> {
const response = await this.SubmitTx(
actions,
[ecc.privateToPublic(payer_prv_key)],
[payer_prv_key]
) as TransactResult;
return {
TxID: response.transaction_id,
};
}
// Nefty market actions
/**
* Create a new auction with the specified parameters
* @returns create auction transaction id
*/
async createAuction(params: NCCreateAuctionParams, key: string) {
const actions = getCreateAuctionActions(this.getActionParams(params));
return this.submitAuctionTx(actions, key);
}
/**
* Place a new bid into an active auction
* @returns bid transaction id
*/
async placeAuctionBid(params: NCPlaceBidParams, key: string) {
const actions = getPlaceBidActions(this.getActionParams(params));
return this.submitAuctionTx(actions, key);
}
/**
* Claim NFTs whenever you win an auction
* @returns claim transaction id
*/
async claimNftsFromAuction(params: NCClaimNftsParams, key: string) {
const actions = getClaimNftsActions(this.getActionParams(params));
return this.submitAuctionTx(actions, key);
}
/**
* Claim the winning bid as the seller of an auction
* @returns claim transaction id
*/
async claimAuctionWinBid(params: NCClaimWinBidParams, key: string) {
const actions = getClaimWinBidActions(this.getActionParams(params));
return this.submitAuctionTx(actions, key);
}
/**
* Erase an auction as long as it has no bids
* @returns delete transaction id
*/
async eraseAuction(params: NCEraseAuctionParams, key: string) {
const actions = getEraseAuctionActions(this.getActionParams(params));
return this.submitAuctionTx(actions, key);
}
/**
* Edit an auction with the specified parameters, internally it erases the existing one
* and creates a new one with the specified parameters.
* @returns transaction id
*/
async editAuction(params: NCEditAuctionParams, key: string ) {
const actions = getEditAuctionActions(this.getActionParams(params));
return this.submitAuctionTx(actions, key);
}
async SubmitTx(
actions: any[],
public_keys: string[], // testnet ["EOS5PU92CupzxWEuvTMcCNr3G69r4Vch3bmYDrczNSHx5LbNRY7NT"]
private_keys: string[] // testnet ["5KdRwMUrkFssK2nUXASnhzjsN1rNNiy8bXAJoHYbBgJMLzjiXHV"]
) {
const signatureProvider = new JsSignatureProvider(private_keys);
signatureProvider.availableKeys = public_keys;
//@ts-ignore
const rpc = this.nodeos_rpc;
const api = new Api({ rpc, signatureProvider }); //required to submit transactions
const info = await rpc.get_info();
const lastBlockInfo = await rpc.get_block(info.last_irreversible_block_num)
const tzOff = new Date(info.head_block_time).getTimezoneOffset();
var t = new Date((new Date(info.head_block_time)).getTime() + 10 * 60 * 1000 - tzOff * 1000 * 60).toISOString().slice(0, -1);//+10m
const transactionObj: Transaction =
{
actions: actions,
expiration: t,
ref_block_prefix: lastBlockInfo.ref_block_prefix, //info.last_irreversible_block_num
ref_block_num: lastBlockInfo.block_num & 0xffff, // 22774
};
if (this.debug) console.log("actions before serialization: " + JSON.stringify(transactionObj.actions));
const a = await api.serializeActions(transactionObj.actions);
const transaction = { ...transactionObj, actions: a };
const serializedTransaction = api.serializeTransaction(transaction);
const availableKeys = await api.signatureProvider.getAvailableKeys();
const requiredKeys = await api.authorityProvider.getRequiredKeys({ transaction, availableKeys });
const abis = await api.getTransactionAbis(transaction);
// const pushTransactionArgs: PushTransactionArgs = { serializedTransaction, signatures };
let tx = {
chainId: info.chain_id, // from getinfo
requiredKeys: requiredKeys,
serializedTransaction: serializedTransaction,
serializedContextFreeData: undefined,
abis: abis
};
const pushTransactionArgs: PushTransactionArgs = await api.signatureProvider.sign(tx);
/*
let tr = serializedTransaction.buffer.toString();
let eccst = ecc.sign(serializedTransaction, private_keys[0]);
let pub_from_prv = ecc.privateToPublic(private_keys[0]);
let sig = pushTransactionArgs.signatures[0];
let key = ecc.recover(sig, tr);
let c = ecc.verify(sig, tr, public_keys[0]);
console.log("signature verification: return %d", c)*/
return api.pushSignedTransaction(pushTransactionArgs);
};
}