implement erc721
MODIFY
src/enums/log_event_signature.ts
src/enums/log_event_signature.ts
export enum Log_Event_Signature {
- Erc20Transfer = '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef'
+ Erc20Transfer = '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
+ Erc721Transfer = '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
+ Erc721BatchTransfer = '0xf871896b17e9cb7a64941c62c188a4f5c621b86800e3d15452ece01ce56073df',
}
\ No newline at end of file

MODIFY
src/model/base_token.ts
src/model/base_token.ts
@@ -49,6 +49,28 @@ export class BaseToken {
});
}
+ protected processRead<T>(method: BaseContractMethod, option: ITransactionOption = {}): Promise<T> {
+ LOGGER.log("process read");
+ return this.createTransactionConfig(
+ {
+ txConfig: option,
+ isWrite: false,
+ method,
+ isParent: this.contractParam.isParent
+ }).then(config => {
+ LOGGER.log("process read config");
+ if (option.returnTransaction) {
+ return merge(config, {
+ data: method.encodeABI(),
+ to: this.contract.address
+ } as ITransactionConfig);
+ }
+ return method.read(
+ config,
+ );
+ });
+ }
+
protected getContract({ isParent, tokenAddress, abi }: IContractInitParam) {
const client = isParent ? this.client.parent.client :
this.client.child.client;

MODIFY
src/plasma/erc20.ts
src/plasma/erc20.ts
@@ -2,7 +2,6 @@ import { BaseToken, Web3SideChainClient } from "../model";
import BN from "bn.js";
import { ITransactionConfig, ITransactionOption } from "../interfaces";
import { formatAmount, IEventBusPromise, eventBusPromise, merge } from "../utils";
-import { createTransactionConfig } from "../utils/create_tx_config";
import { DepositManager } from "./deposit_manager";
export class ERC20 extends BaseToken {
@@ -25,13 +24,7 @@ export class ERC20 extends BaseToken {
"balanceOf",
userAddress
);
- return createTransactionConfig(
- {
- txConfig: {},
- defaultTxConfig: this.childDefaultConfig,
- }).then(config => {
- return method.read<string>(config);
- });
+ return this.processRead<string>(method, option);
}
approve(amount: BN | string | number, option: ITransactionOption = {}) {

MODIFY
src/pos/erc20.ts
src/pos/erc20.ts
import { Web3SideChainClient } from "../model";
import { ITransactionOption } from "../interfaces";
-import { createTransactionConfig } from "../utils/create_tx_config";
import { RootChainManager } from "./root_chain_manager";
import { formatAmount } from "../utils";
import { POSToken } from "./pos_token";
@@ -31,13 +30,7 @@ export class ERC20 extends POSToken {
"balanceOf",
userAddress
);
- return createTransactionConfig(
- {
- txConfig: option,
- defaultTxConfig: this.childDefaultConfig,
- }).then(config => {
- return method.read<string>(config);
- });
+ return this.processRead<string>(method, option);
}
approve(amount: TYPE_AMOUNT, option?: ITransactionOption) {
@@ -69,12 +62,10 @@ export class ERC20 extends POSToken {
* @memberof ERC20
*/
deposit(amount: TYPE_AMOUNT, userAddress: string, option?: ITransactionOption) {
- console.log("this.rootChainManager", this.rootChainManager['contract'].address);
const amountInABI = this.client.parent.client.encodeParameters(
[formatAmount(amount)],
['uint256'],
);
- console.log("amountInByte", amountInABI);
return this.rootChainManager.deposit(
userAddress,
this.contractParam.tokenAddress,

ADD
src/pos/erc721.ts
+import { Web3SideChainClient } from "../model";
+import { ITransactionOption } from "../interfaces";
+import { RootChainManager } from "./root_chain_manager";
+import { formatAmount } from "../utils";
+import { POSToken } from "./pos_token";
+import { TYPE_AMOUNT } from "../types";
+import { ExitManager } from "./exit_manager";
+import { Log_Event_Signature } from "../enums";
+
+export class ERC721 extends POSToken {
+
+
+ constructor(
+ tokenAddress: string,
+ isParent: boolean,
+ client: Web3SideChainClient,
+ rootChainManager: RootChainManager,
+ exitManager: ExitManager
+ ) {
+ super({
+ isParent,
+ tokenAddress,
+ abi: client.getABI('ChildERC721', 'pos')
+ }, client, rootChainManager, exitManager);
+ }
+
+ private validateMany_(tokenIds) {
+ if (tokenIds.length > 20) {
+ throw new Error('can not process more than 20 tokens');
+ }
+ return tokenIds.map(tokenId => {
+ return formatAmount(tokenId);
+ });
+ }
+
+ isApproved(tokenId: string, option?: ITransactionOption) {
+ const contract = this.contract;
+ const method = contract.method(
+ "getApproved",
+ tokenId
+ );
+ return Promise.all([
+ this.processRead<string>(method, option),
+ this.getPredicateAddress()
+ ]).then(result => {
+ return result[0] === result[1];
+ });
+ }
+
+ isApprovedAll(userAddress: string, option?: ITransactionOption) {
+ const contract = this.contract;
+
+ return this.getPredicateAddress().then(predicateAddress => {
+ const method = contract.method(
+ "isApprovedForAll",
+ userAddress,
+ predicateAddress
+ );
+ return this.processRead<boolean>(method, option);
+ });
+
+ }
+
+ approve(tokenId: TYPE_AMOUNT, option?: ITransactionOption) {
+ const contract = this.contract;
+ return this.getPredicateAddress().then(predicateAddress => {
+ const method = contract.method(
+ "approve",
+ predicateAddress,
+ formatAmount(tokenId)
+ );
+ return this.processWrite(method, option);
+ });
+ }
+
+ approveAll(option?: ITransactionOption) {
+ const contract = this.contract;
+ return this.getPredicateAddress().then(predicateAddress => {
+ const method = contract.method(
+ "setApprovalForAll",
+ predicateAddress,
+ true
+ );
+ return this.processWrite(method, option);
+ });
+ }
+
+
+ deposit(tokenId: TYPE_AMOUNT, userAddress: string, option?: ITransactionOption) {
+ const amountInABI = this.client.parent.client.encodeParameters(
+ [formatAmount(tokenId)],
+ ['uint256'],
+ );
+ return this.rootChainManager.deposit(
+ userAddress,
+ this.contractParam.tokenAddress,
+ amountInABI,
+ option
+ );
+ }
+
+ depositMany(tokenIds: TYPE_AMOUNT[], userAddress: string, option?: ITransactionOption) {
+ const tokensInUint256 = this.validateMany_(tokenIds);
+
+ const amountInABI = this.client.parent.client.encodeParameters(
+ tokensInUint256,
+ ['uint256[]'],
+ );
+ return this.rootChainManager.deposit(
+ userAddress,
+ this.contractParam.tokenAddress,
+ amountInABI,
+ option
+ );
+ }
+
+ withdrawStart(tokenId: TYPE_AMOUNT, option?: ITransactionOption) {
+ const contract = this.contract;
+ const method = contract.method(
+ "withdraw",
+ formatAmount(tokenId)
+ );
+ return this.processWrite(method, option);
+ }
+
+ withdrawStartMany(tokenIds: TYPE_AMOUNT[], option?: ITransactionOption) {
+ const tokensInUint256 = this.validateMany_(tokenIds);
+ const contract = this.contract;
+ const method = contract.method(
+ "withdrawBatch",
+ tokensInUint256
+ );
+ return this.processWrite(method, option);
+ }
+
+ withdrawExit(burnTransactionHash: string, option?: ITransactionOption) {
+ return this.exitManager.buildPayloadForExit(
+ burnTransactionHash,
+ Log_Event_Signature.Erc721Transfer,
+ false
+ ).then(payload => {
+ return this.rootChainManager.exit(
+ payload, option
+ );
+ });
+ }
+
+ withdrawExitMany(burnTransactionHash: string, option?: ITransactionOption) {
+ return this.exitManager.buildPayloadForExit(
+ burnTransactionHash,
+ Log_Event_Signature.Erc721BatchTransfer,
+ false
+ ).then(payload => {
+ return this.rootChainManager.exit(
+ payload, option
+ );
+ });
+ }
+
+ withdrawExitFaster(burnTransactionHash: string, option?: ITransactionOption) {
+ return this.exitManager.buildPayloadForExit(
+ burnTransactionHash,
+ Log_Event_Signature.Erc721Transfer,
+ true
+ ).then(payload => {
+ return this.rootChainManager.exit(
+ payload, option
+ );
+ });
+ }
+
+ withdrawExitFasterMany(burnTransactionHash: string, option?: ITransactionOption) {
+ return this.exitManager.buildPayloadForExit(
+ burnTransactionHash,
+ Log_Event_Signature.Erc721BatchTransfer,
+ true
+ ).then(payload => {
+ return this.rootChainManager.exit(
+ payload, option
+ );
+ });
+ }
+
+ isExited(txHash: string) {
+ if (!txHash) {
+ throw new Error(`txHash not provided`);
+ }
+ return this.exitManager.getExitHash(
+ txHash, Log_Event_Signature.Erc721Transfer
+ ).then(exitHash => {
+ return this.rootChainManager.isExitProcessed(
+ exitHash
+ );
+ });
+ }
+
+ isExitedMany(txHash: string) {
+ if (!txHash) {
+ throw new Error(`txHash not provided`);
+ }
+ return this.exitManager.getExitHash(
+ txHash, Log_Event_Signature.Erc721BatchTransfer
+ ).then(exitHash => {
+ return this.rootChainManager.isExitProcessed(
+ exitHash
+ );
+ });
+ }
+
+}
\ No newline at end of file

MODIFY
src/pos/index.ts
src/pos/index.ts
@@ -6,6 +6,7 @@ import { LOGGER } from "../constant";
import { ExitManager } from "./exit_manager";
import { RootChain } from "./root_chain";
import { initService } from "../services";
+import { ERC721 } from "./erc721";
export class POSClient {
@@ -60,6 +61,16 @@ export class POSClient {
);
}
+ erc721(tokenAddress, isParent?: boolean) {
+ return new ERC721(
+ tokenAddress,
+ isParent,
+ this.client_,
+ this.rootChainManager,
+ this.exitManager
+ );
+ }
+
/**
* check whether a txHash is checkPointed
*
@@ -73,15 +84,15 @@ export class POSClient {
);
}
- getBalanceUsingRPC() {
- return this.client_.child.client.sendRPCRequest({
- jsonrpc: '2.0',
- method: 'eth_getBalance',
- params: [
- '0x0ef2e86a73c7be7f767d7abe53b1d4cbfbccbf3a',
- 'latest'
- ],
- id: new Date().getTime()
- });
- }
+ // getBalanceUsingRPC() {
+ // return this.client_.child.client.sendRPCRequest({
+ // jsonrpc: '2.0',
+ // method: 'eth_getBalance',
+ // params: [
+ // '0x0ef2e86a73c7be7f767d7abe53b1d4cbfbccbf3a',
+ // 'latest'
+ // ],
+ // id: new Date().getTime()
+ // });
+ // }
}
\ No newline at end of file

DELETE
src/utils/create_tx_config.ts
-import { ITransactionResult, ITransactionConfig } from "../interfaces";
-import { BaseWeb3Client } from "../model";
-import { BaseContractMethod } from "../abstracts";
-
-interface ITransactionConfigParam {
- txConfig: ITransactionConfig;
- defaultTxConfig: ITransactionConfig;
- method?: BaseContractMethod;
- client?: BaseWeb3Client;
- isWrite?: boolean;
-}
-
-export const createTransactionConfig = async ({ txConfig, defaultTxConfig, method, client, isWrite }: ITransactionConfigParam) => {
- txConfig = Object.assign(defaultTxConfig, txConfig || {});
- console.log("txConfig", txConfig);
- if (isWrite) {
- const [gas, gasPrice, nonce, chainId] = await Promise.all([
- !(txConfig.gas)
- ? method.estimateGas({ from: txConfig.from, value: txConfig.value })
- : txConfig.gas,
- !txConfig.gasPrice ? client.getGasPrice() : txConfig.gasPrice,
- !txConfig.nonce ? client.getTransactionCount(txConfig.from as string, 'pending') : txConfig.nonce,
- !txConfig.chainId ? client.getChainId() : txConfig.chainId,
- ]);
-
- txConfig.gas = gas;
- txConfig.gasPrice = gasPrice;
- txConfig.nonce = nonce;
- txConfig.chainId = chainId;
- }
- return txConfig;
-};
\ No newline at end of file

implement erc721