Skip to content

Commit

Permalink
add: custom contract
Browse files Browse the repository at this point in the history
  • Loading branch information
nitinmittal23 committed Feb 12, 2024
1 parent ef6c352 commit a227a44
Show file tree
Hide file tree
Showing 11 changed files with 213 additions and 14 deletions.
14 changes: 13 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,20 @@ const erc20 = new client.erc20(tokenAddress, networkId);
const balance = erc20.getBalance(address);
```

For the complete function implementation, please refer to the example [here](./test/debug_web3.js) or codebase available [here](./src/lxly/index.ts).
### Custom Contracts

```typescript
// Initialize Custom contract
const customContract = new client.contract(abi, tokenAddress, networkId);

// read contract
await customContract.read(methodName, ...args);

// write contract
await customContract.write(transactionOptions = {}, methodName, ...args);
```

For the complete function implementation, please refer to the example [here](./test/debug_web3.js) or codebase available [here](./src/lxly/index.ts).

## Support

Expand Down
3 changes: 3 additions & 0 deletions src/interfaces/contract_init_param.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import { AbiItem } from "../types";

export interface IContractInitParam {
address: string;
networkId: number;
bridgeAdapterAddress?: string;
abi?: AbiItem[];
/**
* used to get the predicate
*
Expand Down
1 change: 1 addition & 0 deletions src/interfaces/transaction_option.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ import { ITransactionRequestConfig } from "./transaction_config";

export interface ITransactionOption extends ITransactionRequestConfig {
returnTransaction?: boolean;
isRefuel?: boolean;
}
108 changes: 108 additions & 0 deletions src/lxly/contract.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import { isHexString } from 'ethereumjs-util';
import { ITransactionOption } from "../interfaces";
import { AbiItem } from "../types";
import { BaseToken, Web3SideChainClient } from "../utils";
import { IBaseClientConfig } from "../interfaces";

export class Contract extends BaseToken<IBaseClientConfig> {

constructor(
abi: AbiItem[],
tokenAddress: string,
networkId: number,
client: Web3SideChainClient<IBaseClientConfig>,
) {
super({
networkId,
address: tokenAddress,
abi,
name: '',
}, client);
}

/**
* Read from contract
*
* @param {string} method - Method to call
* @param {any[]} args - method arguments
* @returns
* @memberof Contract
*/
read(method: string, ...args: any[]) {
return this.getContract().then(contract => {
const methodInstance = contract.method(
method,
...args
);
return this.processRead<any>(methodInstance);
});
}

/**
* write to contract
*
* @param {ITransactionOption} option - options
* @param {string} method - Method to call
* @param {any[]} args - method arguments
* @returns
* @memberof Contract
*/
write(option: ITransactionOption, method: string, ...args: any[]) {
return this.getContract().then(contract => {
const methodInstance = contract.method(
method,
...args
);
return this.processWrite(methodInstance, option);
});
}

/**
* encode abi call
* @param {string} method - Method to call
* @param {any[]} args - method arguments
* @returns
* @memberof Contract
*/
encodeAbi(method: string, ...args: any[]) {
return this.getContract().then(contract => {
const methodInstance = contract.method(
method,
...args
);
return methodInstance.encodeABI();
});
}

/**
* get {r, s, v} from signature
* @param {string} signature
*
* @returns
* @memberof ERC20
*/
getSignatureParameters(signature: string) {
const client = this.client.providers[this.contractParam.networkId].provider;
if (!isHexString(signature)) {
throw new Error(
'Given value "'.concat(signature, '" is not a valid hex string.'),
);
}

if (signature.slice(0, 2) !== '0x') {
signature = '0x'.concat(signature);
}

const r = signature.slice(0, 66);
const s = '0x'.concat(signature.slice(66, 130));
let v = client.hexToNumber('0x'.concat(signature.slice(130, 132)));
if (![27, 28].includes(v as any)) {
v += 27;
}
return {
r: r,
s: s,
v: v,
};
}
}
8 changes: 4 additions & 4 deletions src/lxly/erc20.ts
Original file line number Diff line number Diff line change
Expand Up @@ -356,9 +356,9 @@ export class ERC20 extends Token {
* @returns
* @memberof ERC20
*/
claimCustomERC20(transactionHash: string, sourceNetworkId: number, isRefuel?: boolean, option?: ITransactionOption) {
claimCustomERC20(transactionHash: string, sourceNetworkId: number, option?: ITransactionOption) {
return this.bridgeUtil.buildPayloadForClaim(
transactionHash, sourceNetworkId, isRefuel || false
transactionHash, sourceNetworkId, option.isRefuel || false
).then(payload => {
if (payload.smtProofRollup) {
return this.bridge.claimMessageNew(
Expand Down Expand Up @@ -403,9 +403,9 @@ export class ERC20 extends Token {
* @returns
* @memberof ERC20
*/
claimAsset(transactionHash: string, sourceNetworkId: number, isRefuel?: boolean, option?: ITransactionOption) {
claimAsset(transactionHash: string, sourceNetworkId: number, option?: ITransactionOption) {
return this.bridgeUtil.buildPayloadForClaim(
transactionHash, sourceNetworkId, isRefuel || false
transactionHash, sourceNetworkId, option.isRefuel || false
).then(payload => {
if (payload.smtProofRollup) {
return this.bridge.claimAssetNew(
Expand Down
25 changes: 23 additions & 2 deletions src/lxly/index.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import { ERC20 } from "./erc20";
import { Contract } from "./contract";
import { Bridge } from "./bridge";
import { BridgeUtil } from "./bridge_util";
import { BridgeClient, setProofApi } from "../utils";
import { IBaseClientConfig, IContracts, IWrappers } from "../interfaces";
import { config as urlConfig } from "../config";
import { service } from "../services";
import { Wrapper } from "./wrapper";
import { AbiItem } from "../types";

export * from "./bridge";
export * from "./bridge_util";
Expand All @@ -19,15 +21,15 @@ export class LxLyClient extends BridgeClient {
const client = this.client;
return client.init(config).then(_ => {
for (const [key, value] of Object.entries(config.providers)) {
if (value.configuration.bridgeAddress){
if (value.configuration.bridgeAddress) {
this.bridges[key] = new Bridge(
this.client,
value.configuration.bridgeAddress,
Number(key)
);
}

if (value.configuration.wrapperAddress){
if (value.configuration.wrapperAddress) {
this.wrappers[key] = new Wrapper(
this.client,
value.configuration.wrapperAddress,
Expand Down Expand Up @@ -68,6 +70,25 @@ export class LxLyClient extends BridgeClient {
);
}

/**
* creates instance of ERC20 token
*
* @param {AbiItem[]} abi
* @param {string} tokenAddress
* @param {number} networkId
*
* @returns
* @memberof Contract
*/
contract(abi: AbiItem[], tokenAddress: string, networkId: number) {
return new Contract(
abi,
tokenAddress,
networkId,
this.client,
);
}

private getContracts_(networkId) {
return {
bridge: this.bridges[networkId],
Expand Down
29 changes: 28 additions & 1 deletion src/types/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,30 @@
import { BaseBigNumber } from "../abstracts";

export type TYPE_AMOUNT = BaseBigNumber | string | number;
export type TYPE_AMOUNT = BaseBigNumber | string | number;

export type AbiInput = {
name: string;
type: string;
internalType?: string;
indexed?: boolean;
};

export type AbiOutput = {
name: string;
type: string;
internalType?: string;
};

export type AbiItem = {
name?: string;
type: string;
constant?: boolean;
payable?: boolean;
stateMutability?: string;
gas?: number;
target?: string;
signature?: string;
inputs?: AbiInput[];
outputs?: AbiOutput[];
anonymous?: boolean;
};
8 changes: 7 additions & 1 deletion src/utils/base_token.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,18 @@ export class BaseToken<T_CLIENT_CONFIG> {
return promiseResolve<BaseContract>(this.contract_ as any);
}
const contractParam = this.contractParam;
const abi = this.client.abiManager.getABI(contractParam.name);
const abi = contractParam.abi || this.client.abiManager.getABI(contractParam.name);
if (!abi) {
return Promise.reject(new Error(`Abi not found`));
}
this.contract_ = this.getContract_({
abi,
networkId: contractParam.networkId,
tokenAddress: contractParam.address
});
if (!this.contract_) {
return Promise.reject(new Error(`Cannot find provider for network ${contractParam.networkId}`));
}
return Promise.resolve(this.contract_);
}

Expand Down
26 changes: 23 additions & 3 deletions test/debug_web3.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,9 @@ const execute = async () => {
// var tx = await N0ERC20Token.bridgeAsset("10000000000000000000", from, 1, {returnTransaction: false});
// return console.log("hash", await tx.getTransactionHash());

// isBridgeClaimable
var result = await client.isBridgeClaimable('0x15f028fc6b2e9aff6ada9fc557c9666b99c238ae9b24739770cab3ec532292e2', 1);
return console.log('result', result);
// // isBridgeClaimable
// var result = await client.isBridgeClaimable('0x15f028fc6b2e9aff6ada9fc557c9666b99c238ae9b24739770cab3ec532292e2', 1);
// return console.log('result', result);

// // isBridgeClaimed
// var result = await client.isBridged('0xdb4147ed0db73a52099b4136e39b9df4de92d74b5ecb864f367446baddbacdae', 0, 1);
Expand Down Expand Up @@ -113,6 +113,26 @@ const execute = async () => {
// // bridge with Permit
// var tx = await N0ERC20Token.bridgeAssetWithPermit("10", from, 1, {returnTransaction: true});
// return console.log("hash", tx);

// // CUSTOM CONTRACT
// let abi = [{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"addValue","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"number","type":"uint256"}],"name":"addValue","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claimableAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"drain","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"randomValue","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"number","type":"uint256"}],"name":"randomValueByNumber","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"stateMutability":"payable","type":"receive"}]

// const customContract = client.contract(abi, "0xbe264257Be052BF867524D2640F6d5305d4263C8", 0);

// console.log('claimableAmount', await customContract.read('claimableAmount'))

// console.log('owner', await customContract.read('owner'))

// console.log('random value', await customContract.read('randomValue'))

// console.log('random value by number', await customContract.read('randomValueByNumber', 4))

// const tx = await customContract.write({returnTransaction: false}, 'addValue');
// console.log('addValue', await tx.getTransactionHash());

// const tx = await customContract.write({returnTransaction: false}, 'addValue', 3);
// // console.log('addValue', tx);
// console.log('addValue', await tx.getTransactionHash());
}

execute().then(_ => {
Expand Down
1 change: 1 addition & 0 deletions test/install_lib.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const packageInfo = JSON.parse(content)
if (packageInfo) {
const version = packageInfo.version
console.log('version', version)
execSync(`rm -rf node_modules`)
execSync(`npm i ../maticnetwork-lxlyjs-${version}.tgz`)
} else {
throw 'no package found'
Expand Down
4 changes: 2 additions & 2 deletions test/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit a227a44

Please sign in to comment.