create pos client
MODIFY
src/abstracts/contract_method.ts
src/abstracts/contract_method.ts
import { ITransactionConfig, ISendResult } from "../interfaces";
export abstract class BaseContractMethod {
- abstract read<T>(tx: ITransactionConfig,): Promise<T>;
+ abstract read<T>(tx?: ITransactionConfig,): Promise<T>;
abstract write(tx: ITransactionConfig,): ISendResult;
abstract estimateGas(tx: ITransactionConfig,): Promise<number>;
abstract encodeABI(): any;

MODIFY
src/interfaces/index.ts
src/interfaces/index.ts
@@ -7,3 +7,4 @@ export * from "./transaction";
export * from "./transaction_option";
export * from "./contract_init_param";
export * from "./tx_receipt";
+export * from "./pos_client_config";
\ No newline at end of file

ADD
src/interfaces/pos_client_config.ts
+export interface IPOSClientConfig {
+ network: string;
+ version: string;
+ parent: {
+ provider: any;
+ defaultConfig: {
+ from: string;
+ }
+ };
+ child: {
+ provider: any;
+ defaultConfig: {
+ from: string;
+ }
+ };
+ rootChainManager?: string;
+ log?: boolean;
+}
\ No newline at end of file

MODIFY
src/model/base_token.ts
src/model/base_token.ts
@@ -5,6 +5,7 @@ import { BaseContract } from "./eth_contract";
import { eventBusPromise, merge, IEventBusPromise } from "../utils";
import { EXTRA_GAS_FOR_PROXY_CALL } from "../constant";
import { ITransactionReceipt } from "../interfaces";
+import { ContractWriteResult } from "./contract_write_result";
interface ITransactionConfigParam {
txConfig: ITransactionConfig;
@@ -18,16 +19,14 @@ export class BaseToken {
contract: BaseContract;
constructor(
- private contractParam: IContractInitParam,
+ public contractParam: IContractInitParam,
public client: Web3SideChainClient,
) {
this.contract = this.getContract(contractParam);
}
- protected processWrite(method: BaseContractMethod, option: ITransactionOption) {
- const result = eventBusPromise<ITransactionReceipt>((res, rej) => {
- // tslint:disable-next-line
- this.createTransactionConfig(
+ protected processWrite(method: BaseContractMethod, option: ITransactionOption): Promise<ContractWriteResult> {
+ return this.createTransactionConfig(
{
txConfig: option,
isWrite: true,
@@ -35,33 +34,17 @@ export class BaseToken {
isParent: true
}).then(config => {
if (option.returnTransaction) {
- return res(
- merge(config, {
+ return merge(config, {
data: method.encodeABI(),
to: this.contract.address
- } as ITransactionConfig)
- );
+ } as ITransactionConfig);
}
const methodResult = method.write(
config,
);
- methodResult.onTransactionHash = (txHash) => {
- result.emit("txHash", txHash);
- };
- methodResult.onError = (err, receipt) => {
- rej({
- error: err,
- receipt
- });
- };
- methodResult.onReceipt = (receipt) => {
- result.emit("receipt", receipt);
- res(receipt);
- result.destroy();
- };
- }) as IEventBusPromise<any>;
+ return new ContractWriteResult(methodResult);
+
});
- return result;
}
getContract({ isParent, tokenAddress, abi }: IContractInitParam) {
@@ -80,7 +63,6 @@ export class BaseToken {
createTransactionConfig = async ({ txConfig, method, isParent, isWrite }: ITransactionConfigParam) => {
txConfig = Object.assign(this.parentDefaultConfig, txConfig || {});
- console.log("txConfig", txConfig);
const client = isParent ? this.client.parent.client :
this.client.child.client;
if (isWrite) {

ADD
src/model/contract_write_result.ts
+import { ISendResult, ITransactionReceipt } from "../interfaces";
+
+export class ContractWriteResult {
+ private result_: ISendResult;
+
+ constructor(result_: ISendResult) {
+ this.result_ = result_;
+ }
+
+ getReceipt() {
+ return new Promise<ITransactionReceipt>((res, rej) => {
+ this.result_.onReceipt = res;
+ this.result_.onError = rej;
+ });
+ }
+
+ getTransactionHash() {
+ return new Promise<string>((res, rej) => {
+ this.result_.onTransactionHash = res;
+ this.result_.onError = rej;
+ });
+ }
+}
\ No newline at end of file

MODIFY
src/model/index.ts
src/model/index.ts
@@ -2,3 +2,4 @@ export * from "./base_token";
export * from "./web3_side_chain_client";
export * from "./web3_client";
export * from "./eth_contract";
+export * from "./contract_write_result";

MODIFY
src/model/web3_side_chain_client.ts
src/model/web3_side_chain_client.ts
@@ -52,8 +52,8 @@ export class Web3SideChainClient {
// ])
}
- getABI(name: string) {
- return this.metaNetwork.abi(name);
+ getABI(name: string, type?: string) {
+ return this.metaNetwork.abi(name, type);
}
get mainContracts() {

ADD
src/pos/erc20.ts
+import { BaseToken, Web3SideChainClient } from "../model";
+import { ITransactionOption } from "../interfaces";
+import { createTransactionConfig } from "../utils/create_tx_config";
+import { RootChainManager } from "./root_chain_manager";
+import BN from "bn.js";
+import { formatAmount } from "../utils";
+import { POSToken } from "./pos_token";
+
+export class ERC20 extends POSToken {
+
+
+ constructor(
+ tokenAddress: string,
+ isParent: boolean,
+ client: Web3SideChainClient,
+ rootChainManager: RootChainManager
+ ) {
+ super({
+ isParent,
+ tokenAddress,
+ abi: client.getABI('ChildERC20', 'pos')
+ }, client, rootChainManager);
+ }
+
+
+
+ getBalance(userAddress: string, option: ITransactionOption = {}) {
+ const contract = this.contract;
+ const method = contract.method(
+ "balanceOf",
+ userAddress
+ );
+ return createTransactionConfig(
+ {
+ txConfig: {},
+ defaultTxConfig: this.childDefaultConfig,
+ }).then(config => {
+ return method.read<string>(config);
+ });
+ }
+
+ approve(amount: BN | string | number, option: ITransactionOption = {}) {
+ const contract = this.contract;
+ return this.getPredicateAddress().then(predicateAddress => {
+ const method = contract.method(
+ "approve",
+ this.predicateAddress,
+ formatAmount(amount)
+ );
+ return this.processWrite(method, option);
+ });
+ }
+
+ approveMax(option: ITransactionOption = {}) {
+ return this.approve(
+ '0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'
+ , option
+ );
+ }
+}
\ No newline at end of file

MODIFY
src/pos/index.ts
src/pos/index.ts
+import { ERC20 } from "./erc20";
+import { RootChainManager } from "./root_chain_manager";
+import { Web3SideChainClient } from "../model";
+import { IPlasmaClientConfig, IPOSClientConfig } from "../interfaces";
+import { LOGGER } from "../constant";
+
export class POSClient {
+ rootChainManager: RootChainManager;
+ private client_: Web3SideChainClient;
+
+
+ constructor(config: IPOSClientConfig) {
+ this.client_ = new Web3SideChainClient(config);
+
+
+ const mainContracts = this.client_.mainContracts;
+
+ config = Object.assign(
+ {
+
+ rootChainManager: mainContracts.POSContracts.RootChainManagerProxy
+ } as IPOSClientConfig,
+ config
+ );
+
+ this.rootChainManager = new RootChainManager(
+ this.client_.parent.client,
+ config.rootChainManager,
+ this.client_.getABI('RootChainManager', 'pos')
+ );
+
+ LOGGER.enableLog(config.log);
+ }
+
+ erc20(tokenAddress, isParent?: boolean) {
+ return new ERC20(
+ tokenAddress,
+ isParent,
+ this.client_,
+ this.rootChainManager
+ );
+ }
}
\ No newline at end of file

ADD
src/pos/pos_token.ts
+import { BaseToken, Web3SideChainClient } from "../model";
+import { ITransactionOption, IContractInitParam } from "../interfaces";
+import { RootChainManager } from "./root_chain_manager";
+
+export class POSToken extends BaseToken {
+
+ predicateAddress: string;
+
+ constructor(
+ contractParam: IContractInitParam,
+ client: Web3SideChainClient,
+ public rootChainManager: RootChainManager
+ ) {
+ super(contractParam, client);
+ }
+
+ async getPredicateAddress() {
+ if (this.predicateAddress) {
+ return this.predicateAddress;
+ }
+ const tokenType = await this.rootChainManager.method("tokenToType", this.contractParam.tokenAddress).read();
+ if (!tokenType) {
+ throw new Error('Invalid Token Type');
+ }
+ const predicateAddress = await this.rootChainManager.method
+ (
+ "typeToPredicate", tokenType
+ ).read<string>();
+ return predicateAddress;
+ }
+}
\ No newline at end of file

ADD
src/pos/root_chain_manager.ts
+import { BaseContract, BaseWeb3Client } from "../model";
+
+export class RootChainManager {
+
+ contract: BaseContract;
+
+ constructor(private client_: BaseWeb3Client, address: string, abi) {
+ this.contract = this.client_.getContract(
+ address,
+ abi
+ );
+ }
+
+ method(methodName: string, ...args) {
+ return this.contract.method(methodName, ...args);
+ }
+}
\ No newline at end of file

MODIFY
test/debug.js
test/debug.js
@@ -26,12 +26,17 @@ const execute = async () => {
}
});
- const childErc20 = matic.erc20(erc20TokenMumbaiAddress);
+ // const childErc20 = matic.erc20(erc20TokenMumbaiAddress);
- const balance = await childErc20.getBalance(from);
- console.log('balance', balance);
+ // const balance = await childErc20.getBalance(from);
+ // console.log('balance', balance);
- // const rootTokenErc20 = matic.erc20(goerliTokenERC20, true);
+ const rootTokenErc20 = matic.erc20(goerliTokenERC20, true);
+ const approveResult = await rootTokenErc20.approve('1000000000000000');
+ const txHash = await approveResult.getTransactionHash();
+ console.log("txHash", txHash);
+ const txReceipt = await approveResult.getReceipt();
+ console.log("txReceipt", txReceipt);
// const promise = rootTokenErc20.approve(
// '1000000000000000'
// )

create pos client