diff --git a/packages/contractkit/README.md b/packages/contractkit/README.md index 700818b091b..aada1998189 100644 --- a/packages/contractkit/README.md +++ b/packages/contractkit/README.md @@ -36,9 +36,7 @@ const kit = newKit('https://alfajores-infura.celo-testnet.org:8545') To access web3: ```ts -const web3 = kit.web3 - -web3.eth.getBalance(someAddress) +await kit.web3.eth.getBalance(someAddress) ``` ### Setting Default Tx Options @@ -46,12 +44,17 @@ web3.eth.getBalance(someAddress) `kit` allows you to set default transaction options: ```ts -import { CeloContract } from '@celo/contractkit' - -// default from -kit.defaultAccount = myAddress -// paid gas in celo dollars -await kit.setGasCurrency(CeloContract.StableToken) +import { newKit, CeloContract } from '@celo/contractkit' + +async function getKit(myAddress: string) { + const kit = newKit('https://alfajores-infura.celo-testnet.org:8545') + + // default from + kit.defaultAccount = myAddress + // paid gas in celo dollars + await kit.setGasCurrency(CeloContract.StableToken) + return kit +} ``` ### Interacting with cGold & cDollar @@ -60,7 +63,7 @@ celo-blockchain has two initial coins: cGold and cDollar (stableToken). Both implement the ERC20 standard, and to interact with them is as simple as: ```ts -const goldtoken = await kit.contract.getGoldToken() +const goldtoken = await kit.contracts.getGoldToken() const balance = await goldtoken.balanceOf(someAddress) ``` @@ -80,7 +83,7 @@ const receipt = await tx.waitReceipt() To interact with cDollar, is the same but with a different contract: ```ts -const stabletoken = await kit.contract.getStableToken() +const stabletoken = await kit.contracts.getStableToken() ``` ### Interacting with Other Contracts @@ -92,6 +95,9 @@ For the moment, we have contract wrappers for: - Exchange (Uniswap kind exchange between Gold and Stable tokens) - Validators - LockedGold +- GoldToken +- StableToken +- Attestations In the following weeks will add wrapper for all other contracts @@ -107,6 +113,24 @@ const web3Exchange = await kit._web3Contracts.getExchange() We expose native wrappers for all Celo core contracts. +The complete list of Celo Core contracts is: + + - Attestations + - LockedGold + - Escrow + - Exchange + - GasCurrencyWhitelist + - GasPriceMinimum + - GoldToken + - Governance + - MultiSig + - Random + - Registry + - Reserve + - SortedOracles + - StableToken + - Validators + ## A Note About Contract Addresses Celo Core Contracts addresses, can be obtained by looking at the `Registry` contract. diff --git a/packages/contractkit/src/address-registry.ts b/packages/contractkit/src/address-registry.ts index 88799673500..68efca73dfc 100644 --- a/packages/contractkit/src/address-registry.ts +++ b/packages/contractkit/src/address-registry.ts @@ -10,6 +10,9 @@ const debug = debugFactory('kit:registry') // Registry contract is always predeployed to this address const REGISTRY_CONTRACT_ADDRESS = '0x000000000000000000000000000000000000ce10' +/** + * Celo Core Contract's Address Registry + */ export class AddressRegistry { private readonly registry: Registry private readonly cache: Map = new Map() @@ -19,6 +22,9 @@ export class AddressRegistry { this.registry = newRegistry(kit.web3, REGISTRY_CONTRACT_ADDRESS) } + /** + * Get the address for a `CeloContract` + */ async addressFor(contract: CeloContract): Promise
{ if (!this.cache.has(contract)) { debug('Fetching address from Registry for %s', contract) @@ -35,6 +41,10 @@ export class AddressRegistry { return cachedAddress } + /** + * Get the address for all possible `CeloContract` + */ + async allAddresses(): Promise> { const res: Partial> = {} for (const contract of AllContracts) { diff --git a/packages/contractkit/src/contract-cache.ts b/packages/contractkit/src/contract-cache.ts index c7aa1270524..18f163bd4f0 100644 --- a/packages/contractkit/src/contract-cache.ts +++ b/packages/contractkit/src/contract-cache.ts @@ -50,6 +50,11 @@ interface WrapperCacheMap { [CeloContract.Validators]?: ValidatorsWrapper } +/** + * Kit ContractWrappers factory & cache. + * + * Provides access to all contract wrappers for celo core contracts + */ export class WrapperCache { // private wrapperCache: Map = new Map() private wrapperCache: WrapperCacheMap = {} @@ -99,6 +104,9 @@ export class WrapperCache { return this.getContract(CeloContract.Validators) } + /** + * Get Contract wrapper + */ public async getContract(contract: C) { if (this.wrapperCache[contract] == null) { const instance = await this.kit._web3Contracts.getContract(contract) diff --git a/packages/contractkit/src/index.ts b/packages/contractkit/src/index.ts index 84877b7a0a7..1c8b6bdecf4 100644 --- a/packages/contractkit/src/index.ts +++ b/packages/contractkit/src/index.ts @@ -6,6 +6,10 @@ export * from './kit' export { CeloTransactionObject } from './wrappers/BaseWrapper' export { Roles } from './wrappers/LockedGold' +/** + * Creates a new web3 instance + * @param url node url + */ export function newWeb3(url: string) { return new Web3(url) } diff --git a/packages/contractkit/src/kit.ts b/packages/contractkit/src/kit.ts index 706b03b53ce..ffdc769da74 100644 --- a/packages/contractkit/src/kit.ts +++ b/packages/contractkit/src/kit.ts @@ -19,10 +19,18 @@ import { ValidatorConfig } from './wrappers/Validators' const debug = debugFactory('kit:kit') +/** + * Creates a new instance of `ContractKit` give a nodeUrl + * @param url CeloBlockchain node url + */ export function newKit(url: string) { return newKitFromWeb3(new Web3(url)) } +/** + * Creates a new instance of `ContractKit` give a web3 instance + * @param web3 Web3 instance + */ export function newKitFromWeb3(web3: Web3) { return new ContractKit(web3) } @@ -46,8 +54,11 @@ export interface KitOptions { } export class ContractKit { + /** core contract's address registry */ readonly registry: AddressRegistry + /** factory for core contract's native web3 wrappers */ readonly _web3Contracts: Web3ContractCache + /** factory for core contract's kit wrappers */ readonly contracts: WrapperCache private config: KitOptions @@ -100,7 +111,11 @@ export class ContractKit { } } - async setGasCurrency(token: CeloToken) { + /** + * Set CeloToken to use to pay for gas fees + * @param token cUsd or cGold + */ + async setGasCurrency(token: CeloToken): Promise { this.config.gasCurrency = token === CeloContract.GoldToken ? null : await this.registry.addressFor(token) } @@ -109,11 +124,17 @@ export class ContractKit { addLocalAccount(this.web3, privateKey) } + /** + * Set default account for generated transactions (eg. tx.from ) + */ set defaultAccount(address: Address) { this.config.from = address this.web3.eth.defaultAccount = address } + /** + * Default account for generated transactions (eg. tx.from) + */ get defaultAccount(): Address { return this.web3.eth.defaultAccount } @@ -126,6 +147,14 @@ export class ContractKit { return this.config.gasInflationFactor } + /** + * Set the ERC20 address for the token to use to pay for gas fees. + * The ERC20 must be whitelisted for gas. + * + * Set to `null` to use cGold + * + * @param address ERC20 address + */ set defaultGasCurrency(address: Address | null) { this.config.gasCurrency = address } @@ -142,6 +171,14 @@ export class ContractKit { return this.web3.eth.isSyncing() } + /** + * Send a transaction to celo-blockchain. + * + * Similar to `web3.eth.sendTransaction()` but with following differences: + * - applies kit tx's defaults + * - estimatesGas before sending + * - returns a `TransactionResult` instead of `PromiEvent` + */ async sendTransaction(tx: Tx): Promise { tx = this.fillTxDefaults(tx) diff --git a/packages/contractkit/src/utils/tx-result.ts b/packages/contractkit/src/utils/tx-result.ts index 6ae849bb9cc..1d4ba0ed678 100644 --- a/packages/contractkit/src/utils/tx-result.ts +++ b/packages/contractkit/src/utils/tx-result.ts @@ -5,10 +5,20 @@ import { TransactionReceipt } from 'web3/types' const debug = debugFactory('kit:tx:result') +/** + * Transforms a `PromiEvent` to a `TransactionResult`. + * + * PromiEvents are returned by web3 when we do a `contract.method.xxx.send()` + */ export function toTxResult(pe: PromiEvent) { return new TransactionResult(pe) } +/** + * Replacement interface for web3's `PromiEvent`. Instead of emiting events + * to signal different stages, eveything is exposed as a promise. Which ends + * up being nicer when doing promise/async based programming. + */ export class TransactionResult { private hashFuture = new Future() private receiptFuture = new Future() @@ -34,10 +44,12 @@ export class TransactionResult { }) as any) } + /** Get (& wait for) transaction hash */ getHash() { return this.hashFuture.wait() } + /** Get (& wait for) transaction receipt */ waitReceipt() { return this.receiptFuture.wait() } diff --git a/packages/contractkit/src/web3-contract-cache.ts b/packages/contractkit/src/web3-contract-cache.ts index 872afd68bae..d6475497aa2 100644 --- a/packages/contractkit/src/web3-contract-cache.ts +++ b/packages/contractkit/src/web3-contract-cache.ts @@ -38,6 +38,14 @@ const ContractFactories = { type CFType = typeof ContractFactories type ContractCacheMap = { [K in keyof CFType]?: ReturnType } +/** + * Native Web3 contracts factory and cache. + * + * Exposes accessors to all `CeloContract` web3 contracts. + * + * Mostly a private cache, kit users would normally use + * a contract wrapper + */ export class Web3ContractCache { private cacheMap: ContractCacheMap = {} @@ -86,6 +94,9 @@ export class Web3ContractCache { return this.getContract(CeloContract.Validators) } + /** + * Get native web3 contract wrapper + */ async getContract(contract: C) { if (this.cacheMap[contract] == null) { debug('Initiating contract %s', contract) diff --git a/packages/contractkit/src/wrappers/BaseWrapper.ts b/packages/contractkit/src/wrappers/BaseWrapper.ts index cd8d816f39d..8da2ff80fb9 100644 --- a/packages/contractkit/src/wrappers/BaseWrapper.ts +++ b/packages/contractkit/src/wrappers/BaseWrapper.ts @@ -6,13 +6,16 @@ import { TransactionReceipt } from 'web3/types' import { ContractKit } from '../kit' import { TransactionResult } from '../utils/tx-result' +/** Represents web3 native contract Method */ type Method = (...args: I) => TransactionObject export type NumberLike = string | number | BigNumber +/** Base ContractWrapper */ export abstract class BaseWrapper { constructor(protected readonly kit: ContractKit, protected readonly contract: T) {} + /** Contract address */ get address(): string { // TODO fix typings return (this.contract as any)._address @@ -20,15 +23,20 @@ export abstract class BaseWrapper { } export interface CeloTransactionObject { + /** web3 native TransactionObject. Normally not used */ txo: TransactionObject + /** send the transaction to the chain */ send(params?: Omit): Promise + /** send the transaction and waits for the receipt */ sendAndWaitForReceipt(params?: Omit): Promise } +/** Parse string -> BigNumber */ export function toBigNumber(input: string) { return new BigNumber(input) } +/** Parse string -> int */ export function toNumber(input: string) { return parseInt(input, 10) } @@ -39,10 +47,15 @@ export function parseNumber(input: NumberLike) { type Parser = (input: A) => B +/** Identity Parser */ export function identity(a: A) { return a } +/** + * Tuple parser + * Useful to map different input arguments + */ export function tupleParser(parser0: Parser): (...args: [A0]) => [B0] export function tupleParser( parser0: Parser, diff --git a/packages/contractkit/src/wrappers/GoldTokenWrapper.ts b/packages/contractkit/src/wrappers/GoldTokenWrapper.ts index baa3eb62eba..30a1b30f0ea 100644 --- a/packages/contractkit/src/wrappers/GoldTokenWrapper.ts +++ b/packages/contractkit/src/wrappers/GoldTokenWrapper.ts @@ -13,11 +13,13 @@ export class GoldTokenWrapper extends BaseWrapper { * @returns Amount of allowance. */ allowance = proxyCall(this.contract.methods.allowance, undefined, toBigNumber) + /** * Returns the name of the token. * @returns Name of the token. */ name = proxyCall(this.contract.methods.name, undefined, (a: any) => a.toString()) + /** * Returns the three letter symbol of the token. * @returns Symbol of the token. @@ -28,14 +30,51 @@ export class GoldTokenWrapper extends BaseWrapper { * @returns Number of decimals. */ decimals = proxyCall(this.contract.methods.decimals, undefined, toNumber) + /** * Returns the total supply of the token, that is, the amount of tokens currently minted. * @returns Total supply. */ totalSupply = proxyCall(this.contract.methods.totalSupply, undefined, toBigNumber) + + /** + * Approve a user to transfer Celo Gold on behalf of another user. + * @param spender The address which is being approved to spend Celo Gold. + * @param value The amount of Celo Gold approved to the spender. + * @return True if the transaction succeeds. + */ approve = proxySend(this.kit, this.contract.methods.approve) + + /** + * Transfers Celo Gold from one address to another with a comment. + * @param to The address to transfer Celo Gold to. + * @param value The amount of Celo Gold to transfer. + * @param comment The transfer comment + * @return True if the transaction succeeds. + */ transferWithComment = proxySend(this.kit, this.contract.methods.transferWithComment) + + /** + * Transfers Celo Gold from one address to another. + * @param to The address to transfer Celo Gold to. + * @param value The amount of Celo Gold to transfer. + * @return True if the transaction succeeds. + */ transfer = proxySend(this.kit, this.contract.methods.transfer) + + /** + * Transfers Celo Gold from one address to another on behalf of a user. + * @param from The address to transfer Celo Gold from. + * @param to The address to transfer Celo Gold to. + * @param value The amount of Celo Gold to transfer. + * @return True if the transaction succeeds. + */ transferFrom = proxySend(this.kit, this.contract.methods.transferFrom) + + /** + * Gets the balance of the specified address. + * @param owner The address to query the balance of. + * @return The balance of the specified address. + */ balanceOf = (account: Address) => this.kit.web3.eth.getBalance(account).then(toBigNumber) } diff --git a/packages/contractkit/src/wrappers/LockedGold.ts b/packages/contractkit/src/wrappers/LockedGold.ts index a63e34b8d3c..87ee8c46df4 100644 --- a/packages/contractkit/src/wrappers/LockedGold.ts +++ b/packages/contractkit/src/wrappers/LockedGold.ts @@ -16,6 +16,7 @@ import { export interface VotingDetails { accountAddress: Address voterAddress: Address + /** vote's weight */ weight: BigNumber } @@ -47,19 +48,86 @@ export interface LockedGoldConfig { * Contract for handling deposits needed for voting. */ export class LockedGoldWrapper extends BaseWrapper { - notifyCommitment = proxySend(this.kit, this.contract.methods.notifyCommitment) - createAccount = proxySend(this.kit, this.contract.methods.createAccount) - withdrawCommitment = proxySend(this.kit, this.contract.methods.withdrawCommitment) - redeemRewards = proxySend(this.kit, this.contract.methods.redeemRewards) - newCommitment = proxySend(this.kit, this.contract.methods.newCommitment) - extendCommitment = proxySend(this.kit, this.contract.methods.extendCommitment) + /** + * Notifies a Locked Gold commitment, allowing funds to be withdrawn after the notice + * period. + * @param value The amount of the commitment to eventually withdraw. + * @param noticePeriod The notice period of the Locked Gold commitment. + * @return CeloTransactionObject + */ + notifyCommitment: ( + value: string | number, + noticePeriod: string | number + ) => CeloTransactionObject = proxySend(this.kit, this.contract.methods.notifyCommitment) + + /** + * Creates an account. + * @return CeloTransactionObject + */ + createAccount: () => CeloTransactionObject = proxySend( + this.kit, + this.contract.methods.createAccount + ) + + /** + * Withdraws a notified commitment after the duration of the notice period. + * @param availabilityTime The availability time of the notified commitment. + * @return CeloTransactionObject + */ + withdrawCommitment: ( + availabilityTime: string | number + ) => CeloTransactionObject = proxySend(this.kit, this.contract.methods.withdrawCommitment) + + /** + * Redeems rewards accrued since the last redemption for the specified account. + * @return CeloTransactionObject + */ + redeemRewards: () => CeloTransactionObject = proxySend( + this.kit, + this.contract.methods.redeemRewards + ) + + /** + * Adds a Locked Gold commitment to `msg.sender`'s account. + * @param noticePeriod The notice period for the commitment. + * @return CeloTransactionObject + */ + newCommitment: (noticePeriod: string | number) => CeloTransactionObject = proxySend( + this.kit, + this.contract.methods.newCommitment + ) + + /** + * Rebonds a notified commitment, with notice period >= the remaining time to + * availability. + * + * @param value The amount of the commitment to rebond. + * @param availabilityTime The availability time of the notified commitment. + * @return CeloTransactionObject + */ + extendCommitment: ( + value: string | number, + availabilityTime: string | number + ) => CeloTransactionObject = proxySend(this.kit, this.contract.methods.extendCommitment) + + /** + * Returns whether or not a specified account is voting. + * @param account The address of the account. + * @return Whether or not the account is voting. + */ isVoting = proxyCall(this.contract.methods.isVoting) + /** * Query maximum notice period. * @returns Current maximum notice period. */ maxNoticePeriod = proxyCall(this.contract.methods.maxNoticePeriod, undefined, toBigNumber) + /** + * Returns the weight of a specified account. + * @param _account The address of the account. + * @return The weight of the specified account. + */ getAccountWeight = proxyCall(this.contract.methods.getAccountWeight, undefined, toBigNumber) /** * Get the delegate for a role. @@ -81,6 +149,10 @@ export class LockedGoldWrapper extends BaseWrapper { } } + /** + * Get voting details for an address + * @param accountOrVoterAddress Accout or Voter address + */ async getVotingDetails(accountOrVoterAddress: Address): Promise { const accountAddress = await this.contract.methods .getAccountFromDelegateAndRole(accountOrVoterAddress, Roles.Voting) @@ -93,12 +165,12 @@ export class LockedGoldWrapper extends BaseWrapper { } } - async getLockedCommitmentValue(account: string, noticePeriod: string): Promise { + async getLockedCommitmentValue(account: Address, noticePeriod: string): Promise { const commitment = await this.contract.methods.getLockedCommitment(account, noticePeriod).call() return this.getValueFromCommitment(commitment) } - async getLockedCommitments(account: string): Promise { + async getLockedCommitments(account: Address): Promise { return this.zipAccountTimesAndValuesToCommitments( account, this.contract.methods.getNoticePeriods, @@ -106,12 +178,12 @@ export class LockedGoldWrapper extends BaseWrapper { ) } - async getNotifiedCommitmentValue(account: string, availTime: string): Promise { + async getNotifiedCommitmentValue(account: Address, availTime: string): Promise { const commitment = await this.contract.methods.getNotifiedCommitment(account, availTime).call() return this.getValueFromCommitment(commitment) } - async getNotifiedCommitments(account: string): Promise { + async getNotifiedCommitments(account: Address): Promise { return this.zipAccountTimesAndValuesToCommitments( account, this.contract.methods.getAvailabilityTimes, @@ -119,7 +191,11 @@ export class LockedGoldWrapper extends BaseWrapper { ) } - async getCommitments(account: string): Promise { + /** + * Get commitments for an Account + * @param account Account address + */ + async getCommitments(account: Address): Promise { const locked = await this.getLockedCommitments(account) const notified = await this.getNotifiedCommitments(account) const weight = await this.getAccountWeight(account) @@ -193,7 +269,7 @@ export class LockedGoldWrapper extends BaseWrapper { return new BigNumber(commitment[0]) } - private async getParsedSignatureOfAddress(address: string, signer: string) { + private async getParsedSignatureOfAddress(address: Address, signer: string) { const hash = Web3.utils.soliditySha3({ type: 'address', value: address }) const signature = (await this.kit.web3.eth.sign(hash, signer)).slice(2) return { @@ -204,7 +280,7 @@ export class LockedGoldWrapper extends BaseWrapper { } private async zipAccountTimesAndValuesToCommitments( - account: string, + account: Address, timesFunc: (account: string) => TransactionObject, valueFunc: (account: string, time: string) => Promise ) { diff --git a/packages/contractkit/src/wrappers/StableTokenWrapper.ts b/packages/contractkit/src/wrappers/StableTokenWrapper.ts index da23172394c..ebe68a056d8 100644 --- a/packages/contractkit/src/wrappers/StableTokenWrapper.ts +++ b/packages/contractkit/src/wrappers/StableTokenWrapper.ts @@ -2,6 +2,8 @@ import BigNumber from 'bignumber.js' import { StableToken } from '../generated/types/StableToken' import { BaseWrapper, + CeloTransactionObject, + NumberLike, parseNumber, proxyCall, proxySend, @@ -29,53 +31,75 @@ export interface StableTokenConfig { */ export class StableTokenWrapper extends BaseWrapper { /** - * Querying allowance. - * @param from Account who has given the allowance. - * @param to Address of account to whom the allowance was given. - * @returns Amount of allowance. + * Gets the amount of owner's StableToken allowed to be spent by spender. + * @param accountOwner The owner of the StableToken. + * @param spender The spender of the StableToken. + * @return The amount of StableToken owner is allowing spender to spend. */ allowance = proxyCall(this.contract.methods.allowance, undefined, toBigNumber) + /** - * Returns the name of the token. - * @returns Name of the token. + * @return The name of the stable token. */ - name = proxyCall(this.contract.methods.name, undefined, (a: any) => a.toString()) + name: () => Promise = proxyCall(this.contract.methods.name) + /** - * Returns the three letter symbol of the token. - * @returns Symbol of the token. + * @return The symbol of the stable token. */ - symbol = proxyCall(this.contract.methods.symbol, undefined, (a: any) => a.toString()) + symbol: () => Promise = proxyCall(this.contract.methods.symbol) + /** - * Returns the number of decimals used in the token. - * @returns Number of decimals. + * @return The number of decimal places to which StableToken is divisible. */ decimals = proxyCall(this.contract.methods.decimals, undefined, toNumber) + /** * Returns the total supply of the token, that is, the amount of tokens currently minted. * @returns Total supply. */ totalSupply = proxyCall(this.contract.methods.totalSupply, undefined, toBigNumber) - balanceOf = proxyCall(this.contract.methods.balanceOf, undefined, toBigNumber) + + /** + * Gets the balance of the specified address using the presently stored inflation factor. + * @param owner The address to query the balance of. + * @return The balance of the specified address. + */ + balanceOf: (owner: string) => Promise = proxyCall( + this.contract.methods.balanceOf, + undefined, + toBigNumber + ) + minter = proxyCall(this.contract.methods.minter) owner = proxyCall(this.contract.methods.owner) - valueToUnits = proxyCall( + + /** + * Returns the units for a given value given the current inflation factor. + * @param value The value to convert to units. + * @return The units corresponding to `value` given the current inflation factor. + * @dev We don't compute the updated inflationFactor here because + * we assume any function calling this will have updated the inflation factor. + */ + valueToUnits: (value: NumberLike) => Promise = proxyCall( this.contract.methods.valueToUnits, tupleParser(parseNumber), toBigNumber ) - unitsToValue = proxyCall( + /** + * Returns the value of a given number of units given the current inflation factor. + * @param units The units to convert to value. + * @return The value corresponding to `units` given the current inflation factor. + */ + unitsToValue: (units: NumberLike) => Promise = proxyCall( this.contract.methods.unitsToValue, tupleParser(parseNumber), toBigNumber ) - approve = proxySend(this.kit, this.contract.methods.approve) mint = proxySend(this.kit, this.contract.methods.mint) burn = proxySend(this.kit, this.contract.methods.burn) - transferWithComment = proxySend(this.kit, this.contract.methods.transferWithComment) - transfer = proxySend(this.kit, this.contract.methods.transfer) - transferFrom = proxySend(this.kit, this.contract.methods.transferFrom) + setInflationParameters = proxySend(this.kit, this.contract.methods.setInflationParameters) /** @@ -109,4 +133,55 @@ export class StableTokenWrapper extends BaseWrapper { inflationParameters: res[3], } } + + /** + * Approve a user to transfer StableToken on behalf of another user. + * @param spender The address which is being approved to spend StableToken. + * @param value The amount of StableToken approved to the spender. + * @return True if the transaction succeeds. + */ + approve: (spender: string, value: string | number) => CeloTransactionObject = proxySend( + this.kit, + this.contract.methods.approve + ) + + /** + * Transfer token for a specified address + * @param to The address to transfer to. + * @param value The amount to be transferred. + * @param comment The transfer comment. + * @return True if the transaction succeeds. + */ + transferWithComment: ( + to: string, + value: string | number, + comment: string + ) => CeloTransactionObject = proxySend( + this.kit, + this.contract.methods.transferWithComment + ) + + /** + * Transfers `value` from `msg.sender` to `to` + * @param to The address to transfer to. + * @param value The amount to be transferred. + */ + + transfer: (to: string, value: string | number) => CeloTransactionObject = proxySend( + this.kit, + this.contract.methods.transfer + ) + + /** + * Transfers StableToken from one address to another on behalf of a user. + * @param from The address to transfer StableToken from. + * @param to The address to transfer StableToken to. + * @param value The amount of StableToken to transfer. + * @return True if the transaction succeeds. + */ + transferFrom: ( + from: string, + to: string, + value: string | number + ) => CeloTransactionObject = proxySend(this.kit, this.contract.methods.transferFrom) }