UNPKG

@0xcert/ethereum-value-ledger

Version:

Value ledger module for currency management on the Ethereum blockchain.

203 lines (180 loc) 6.56 kB
import { GenericProvider, Mutation, MutationEventSignature, MutationEventTypeKind } from '@0xcert/ethereum-generic-provider'; import { bigNumberify } from '@0xcert/ethereum-utils'; import { ProviderError, ProviderIssue, ValueLedgerBase, ValueLedgerDeployRecipe, ValueLedgerInfo, ValueLedgerTransferRecipe } from '@0xcert/scaffold'; import approveAccount from '../mutations/approve-account'; import deploy from '../mutations/deploy'; import transfer from '../mutations/transfer'; import transferFrom from '../mutations/transfer-from'; import getAllowance from '../queries/get-allowance'; import getBalance from '../queries/get-balance'; import getInfo from '../queries/get-info'; /** * Ethereum value ledger implementation. */ export class ValueLedger implements ValueLedgerBase { /** * Value ledger Id. Address pointing at the smartcontract. */ protected _id: string; /** * Provider instance. */ protected _provider: GenericProvider; /** * Initialize value ledger. * @param provider Provider class with which we communicate with blockchain. * @param id Address of the erc20 smart contract. */ public constructor(provider: GenericProvider, id: string) { this._provider = provider; this._id = this._provider.encoder.normalizeAddress(id); } /** * Deploys a new smart contract representing value ledger to the blockchain. * @param provider Provider class with which we communicate with blockchain. * @param recipe Data needed to deploy a new value ledger. */ public static async deploy(provider: GenericProvider, recipe: ValueLedgerDeployRecipe) { return deploy(provider, recipe); } /** * Gets an instance of already deployed value ledger. * @param provider Provider class with which we communicate with blockchain. * @param id Address of the erc20 smart contract. */ public static getInstance(provider: GenericProvider, id: string): ValueLedger { return new this(provider, id); } /** * Gets the address of the smart contract that represents this value ledger. */ public get id() { return this._id; } /** * Gets the provider that is used to communicate with blockchain. */ public get provider() { return this._provider; } /** * Gets the amount of value that another account id approved for. * @param accountId Account id. * @param spenderId Account id of the spender. */ public async getApprovedValue(accountId: string, spenderId: string): Promise<string> { accountId = this._provider.encoder.normalizeAddress(accountId); spenderId = this._provider.encoder.normalizeAddress(spenderId as string); return getAllowance(this, accountId, spenderId); } /** * Gets the amount of value a specific account owns. * @param accountId Account id. */ public async getBalance(accountId: string): Promise<string> { accountId = this._provider.encoder.normalizeAddress(accountId); return getBalance(this, accountId); } /** * Gets information(name, symbol, total supply, decimals) about the value ledger. */ public async getInfo(): Promise<ValueLedgerInfo> { return getInfo(this); } /** * Checks if spender is approved for the specific values. * @param accountId Account id. * @param spenderId Account id of spender. * @param value Value amount we are checking against. */ public async isApprovedValue(value: string, accountId: string, spenderId: string): Promise<boolean> { accountId = this._provider.encoder.normalizeAddress(accountId); spenderId = this._provider.encoder.normalizeAddress(spenderId as string); const approved = await getAllowance(this, accountId, spenderId); return bigNumberify(approved).gte(bigNumberify(value)); } /** * Approves another account to operate with a specified amount of value. * @param accountId Account id. * @param value Value amount. */ public async approveValue(value: string, accountId: string): Promise<Mutation> { accountId = this._provider.encoder.normalizeAddress(accountId as string); const approvedValue = await this.getApprovedValue(this.provider.accountId, accountId); if (!bigNumberify(value).isZero() && !bigNumberify(approvedValue).isZero()) { throw new ProviderError(ProviderIssue.ERC20_APPROVAL_RACE_CONDITION); } return approveAccount(this, accountId, value); } /** * Disapproves account for operating with your value. * @param accountId Account id. */ public async disapproveValue(accountId: string): Promise<Mutation> { accountId = this._provider.encoder.normalizeAddress(accountId as string); return approveAccount(this, accountId, '0'); } /** * Transfer value to another account. * @param recipe Data needed for the transfer. */ public async transferValue(recipe: ValueLedgerTransferRecipe): Promise<Mutation> { const senderId = this._provider.encoder.normalizeAddress(recipe.senderId); const receiverId = this._provider.encoder.normalizeAddress(recipe.receiverId); return recipe.senderId ? transferFrom(this, senderId, receiverId, recipe.value) : transfer(this, receiverId, recipe.value); } /** * Gets context for mutation event parsing. * This are event definitions for Value Ledger smart contract event parsing. This method is used * by the Mutation class to provide log information. */ public getContext(): MutationEventSignature[] { return [ { name: 'Transfer', topic: '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef', types: [ { kind: MutationEventTypeKind.INDEXED, name: 'from', type: 'address', }, { kind: MutationEventTypeKind.INDEXED, name: 'to', type: 'address', }, { kind: MutationEventTypeKind.NORMAL, name: 'value', type: 'uint256', }, ], }, { name: 'Approval', topic: '0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925', types: [ { kind: MutationEventTypeKind.INDEXED, name: 'owner', type: 'address', }, { kind: MutationEventTypeKind.INDEXED, name: 'spender', type: 'address', }, { kind: MutationEventTypeKind.NORMAL, name: 'value', type: 'uint256', }, ], }, ]; } }