import BN from 'bn.js'; import { Account } from './account'; import { Connection } from './connection'; import { Contract } from './contract'; import { readKeyFile } from './key_stores/unencrypted_file_system_keystore'; import { PublicKey } from './utils/key_pair'; import { AccountCreator, LocalAccountCreator, UrlAccountCreator } from './account_creator'; import { InMemoryKeyStore, MergeKeyStore } from './key_stores'; export class Near { readonly config: any; readonly connection: Connection; readonly accountCreator: AccountCreator; constructor(config: any) { this.config = config; this.connection = Connection.fromConfig({ networkId: config.networkId, provider: { type: 'JsonRpcProvider', args: { url: config.nodeUrl } }, signer: { type: 'InMemorySigner', keyStore: config.deps.keyStore } }); if (config.masterAccount) { // TODO: figure out better way of specifiying initial balance. // Hardcoded number below is roughly five times the gas cost to dev-deploy with near-shell const initialBalance = config.initialBalance ? new BN(config.initialBalance) : new BN('100000000000000000'); this.accountCreator = new LocalAccountCreator(new Account(this.connection, config.masterAccount), initialBalance); } else if (config.helperUrl) { this.accountCreator = new UrlAccountCreator(this.connection, config.helperUrl); } else { this.accountCreator = null; } } async account(accountId: string): Promise { const account = new Account(this.connection, accountId); await account.state(); return account; } async createAccount(accountId: string, publicKey: PublicKey): Promise { if (!this.accountCreator) { throw new Error('Must specify account creator, either via masterAccount or helperUrl configuration settings.'); } await this.accountCreator.createAccount(accountId, publicKey); return new Account(this.connection, accountId); } /** * Backwards compatibility method. Use `new nearlib.Contract(yourAccount, contractId, { viewMethods, changeMethods })` instead. * @param contractId * @param options */ async loadContract(contractId: string, options: { viewMethods: string[], changeMethods: string[], sender: string }): Promise { const account = new Account(this.connection, options.sender); return new Contract(account, contractId, options); } /** * Backwards compatibility method. Use `yourAccount.sendMoney` instead. * @param amount * @param originator * @param receiver */ async sendTokens(amount: BN, originator: string, receiver: string): Promise { console.warn('near.sendTokens is deprecated. Use `yourAccount.sendMoney` instead.'); const account = new Account(this.connection, originator); const result = await account.sendMoney(receiver, amount); return result.transaction_outcome.id; } } export async function connect(config: any): Promise { // Try to find extra key in `KeyPath` if provided. if (config.keyPath && config.deps && config.deps.keyStore) { try { const accountKeyFile = await readKeyFile(config.keyPath); if (accountKeyFile[0]) { // TODO: Only load key if network ID matches const keyPair = accountKeyFile[1]; const keyPathStore = new InMemoryKeyStore(); await keyPathStore.setKey(config.networkId, accountKeyFile[0], keyPair); if (!config.masterAccount) { config.masterAccount = accountKeyFile[0]; } config.deps.keyStore = new MergeKeyStore([config.deps.keyStore, keyPathStore]); console.log(`Loaded master account ${accountKeyFile[0]} key from ${config.keyPath} with public key = ${keyPair.getPublicKey()}`); } } catch (error) { console.warn(`Failed to load master account key from ${config.keyPath}: ${error}`); } } return new Near(config); }