UNPKG

chedder

Version:
265 lines (234 loc) 9.64 kB
import sha256 from 'js-sha256'; import BN from 'bn.js'; import { Enum, Assignable } from './utils/enums.js'; import { serialize, deserialize } from './utils/serialize.js'; import { KeyType, PublicKey } from './utils/key-pair.js'; import { KeyPair } from './utils/key-pair.js'; //import { Signer } from './signer'; export class FunctionCallPermission extends Assignable { allowance?: BN; receiverId!: string; methodNames!: String[]; } export class FullAccessPermission extends Assignable {} export class AccessKeyPermission extends Enum { functionCall!: FunctionCallPermission fullAccess!: FullAccessPermission } export class AccessKey extends Assignable { nonce!: number permission!: AccessKeyPermission } export function fullAccessKey(): AccessKey { return new AccessKey({ nonce: 0, permission: new AccessKeyPermission({fullAccess: new FullAccessPermission({})}) }); } export function functionCallAccessKey(receiverId: string, methodNames: String[], allowance?: BN): AccessKey { return new AccessKey({ nonce: 0, permission: new AccessKeyPermission({functionCall: new FunctionCallPermission({receiverId, allowance, methodNames})})}); } export class IAction extends Assignable {} class CreateAccount extends IAction {} class DeployContract extends IAction { code!: Uint8Array; } class FunctionCall extends IAction { methodName!: string; args!: Uint8Array; gas!: BN; deposit!: BN; } class Transfer extends IAction { deposit!: BN; } class Stake extends IAction { stake!: BN; publicKey!: PublicKey; } class AddKey extends IAction { publicKey!: PublicKey; accessKey!: AccessKey; } class DeleteKey extends IAction { publicKey!: PublicKey; } class DeleteAccount extends IAction { beneficiaryId!: string; } export function createAccount(): Action { return new Action({createAccount: new CreateAccount({}) }); } export function deployContract(code: Uint8Array): Action { return new Action({ deployContract: new DeployContract({code}) }); } /** * Constructs {@link Action} instance representing contract method call. * * @param methodName the name of the method to call * @param args arguments to pass to method. Can be either plain JS object which gets serialized as JSON automatically * or `Uint8Array` instance which represents bytes passed as is. * @param gas max amount of gas that method call can use * @param deposit amount of NEAR (in yoctoNEAR) to send together with the call */ export function functionCall(methodName: string, args: Uint8Array | object, gas: BN, deposit: BN): Action { const anyArgs = args as any; const isUint8Array = anyArgs.byteLength !== undefined && anyArgs.byteLength === anyArgs.length; const serializedArgs = isUint8Array ? args : Buffer.from(JSON.stringify(args)); return new Action({functionCall: new FunctionCall({methodName, args: serializedArgs, gas, deposit }) }); } export function transfer(deposit: BN): Action { return new Action({transfer: new Transfer({ deposit }) }); } export function stake(stake: BN, publicKey: PublicKey): Action { return new Action({stake: new Stake({ stake, publicKey }) }); } export function addKey(publicKey: PublicKey, accessKey: AccessKey): Action { return new Action({addKey: new AddKey({ publicKey, accessKey}) }); } export function deleteKey(publicKey: PublicKey): Action { return new Action({deleteKey: new DeleteKey({ publicKey }) }); } export function deleteAccount(beneficiaryId: string): Action { return new Action({deleteAccount: new DeleteAccount({ beneficiaryId }) }); } export class Signature extends Assignable { keyType!: KeyType; data!: Uint8Array; } export class Transaction extends Assignable { signerId!: string; publicKey!: PublicKey; nonce!: number; receiverId!: string; actions!: Action[]; blockHash!: Uint8Array; encode(): Uint8Array { return serialize(SCHEMA, this); } static decode(bytes: Buffer): Transaction { return deserialize(SCHEMA, Transaction, bytes); } } export class SignedTransaction extends Assignable { transaction!: Transaction; signature!: Signature; encode(): Uint8Array { return serialize(SCHEMA, this); } static decode(bytes: Buffer): SignedTransaction { return deserialize(SCHEMA, SignedTransaction, bytes); } } /** * Contains a list of the valid transaction Actions available with this API */ export class Action extends Enum { createAccount!: CreateAccount; deployContract!: DeployContract; functionCall!: FunctionCall; transfer!: Transfer; stake!: Stake; addKey!: AddKey; deleteKey!: DeleteKey; deleteAccount!: DeleteAccount; } export const SCHEMA = new Map<Function, any>([ [Signature, {kind: 'struct', fields: [ ['keyType', 'u8'], ['data', [64]] ]}], [SignedTransaction, {kind: 'struct', fields: [ ['transaction', Transaction], ['signature', Signature] ]}], [Transaction, { kind: 'struct', fields: [ ['signerId', 'string'], ['publicKey', PublicKey], ['nonce', 'u64'], ['receiverId', 'string'], ['blockHash', [32]], ['actions', [Action]] ]}], [PublicKey, { kind: 'struct', fields: [ ['keyType', 'u8'], ['data', [32]] ]}], [AccessKey, { kind: 'struct', fields: [ ['nonce', 'u64'], ['permission', AccessKeyPermission], ]}], [AccessKeyPermission, {kind: 'enum', field: 'enum', values: [ ['functionCall', FunctionCallPermission], ['fullAccess', FullAccessPermission], ]}], [FunctionCallPermission, {kind: 'struct', fields: [ ['allowance', {kind: 'option', type: 'u128'}], ['receiverId', 'string'], ['methodNames', ['string']], ]}], [FullAccessPermission, {kind: 'struct', fields: []}], [Action, {kind: 'enum', field: 'enum', values: [ ['createAccount', CreateAccount], ['deployContract', DeployContract], ['functionCall', FunctionCall], ['transfer', Transfer], ['stake', Stake], ['addKey', AddKey], ['deleteKey', DeleteKey], ['deleteAccount', DeleteAccount], ]}], [CreateAccount, { kind: 'struct', fields: [] }], [DeployContract, { kind: 'struct', fields: [ ['code', ['u8']] ]}], [FunctionCall, { kind: 'struct', fields: [ ['methodName', 'string'], ['args', ['u8']], ['gas', 'u64'], ['deposit', 'u128'] ]}], [Transfer, { kind: 'struct', fields: [ ['deposit', 'u128'] ]}], [Stake, { kind: 'struct', fields: [ ['stake', 'u128'], ['publicKey', PublicKey] ]}], [AddKey, { kind: 'struct', fields: [ ['publicKey', PublicKey], ['accessKey', AccessKey] ]}], [DeleteKey, { kind: 'struct', fields: [ ['publicKey', PublicKey] ]}], [DeleteAccount, { kind: 'struct', fields: [ ['beneficiaryId', 'string'] ]}], ]); export function createTransaction(signerId: string, publicKey: PublicKey, receiverId: string, nonce: number, actions: Action[], blockHash: Uint8Array): Transaction { return new Transaction({ signerId, publicKey, nonce, receiverId, actions, blockHash }); } export class createSignedTransactionResult{ constructor( public hash:Uint8Array, public signedTransaction: SignedTransaction ){} } /** * Signs a given transaction from an account with given keys, applied to the given network * return HASH and the signed transaction * @param transaction The Transaction object to sign * @param keyPair The KeyPair to sign the txn */ export function createHashAndSignedTransaction(transaction: Transaction, keyPair:KeyPair): createSignedTransactionResult { const message = serialize(SCHEMA, transaction); const hash = new Uint8Array(sha256.sha256.array(message)); const signature = keyPair.sign(hash) const signedTx = new SignedTransaction({ transaction, signature: new Signature({ keyType: transaction.publicKey.keyType, data: signature.signature }) }); return new createSignedTransactionResult(hash, signedTx); } /** * Signs a given transaction from an account with given keys, applied to the given network * @param transaction The Transaction object to sign * @param keyPair The KeyPair to sign the txn */ export function createSignedTransaction(transaction: Transaction, keyPair:KeyPair): SignedTransaction { let result = createHashAndSignedTransaction(transaction,keyPair); return result.signedTransaction; } /*export async function signTransaction(transaction: Transaction, signer: Signer, accountId?: string, networkId?: string): Promise<[Uint8Array, SignedTransaction]>; export async function signTransaction(receiverId: string, nonce: number, actions: Action[], blockHash: Uint8Array, signer: Signer, accountId?: string, networkId?: string): Promise<[Uint8Array, SignedTransaction]>; export async function signTransaction(...args): Promise<[Uint8Array, SignedTransaction]> { if (args[0].constructor === Transaction) { const [ transaction, signer, accountId, networkId ] = args; return signTransactionObject(transaction, signer, accountId, networkId); } else { const [ receiverId, nonce, actions, blockHash, signer, accountId, networkId ] = args; const publicKey = await signer.getPublicKey(accountId, networkId); const transaction = createTransaction(accountId, publicKey, receiverId, nonce, actions, blockHash); return signTransactionObject(transaction, signer, accountId, networkId); } } */