Skip to content

Commit

Permalink
Merge pull request #7 from celo-tools/0.3.0
Browse files Browse the repository at this point in the history
0.3.0 - Fix deployement transactions and improve CeloWallet
  • Loading branch information
jmrossy authored Jun 17, 2022
2 parents 0916f26 + b2eb21f commit f4163a5
Show file tree
Hide file tree
Showing 12 changed files with 1,231 additions and 363 deletions.
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
.nyc_output
build
node_modules
test
src/**.js
coverage
*.log
Expand Down
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@

A minimal wrapper to make Ethers.JS compatible with the Celo network.

_Note: this is still experimental_

## Install

`npm i @celo-tools/celo-ethers-wrapper`
Expand Down Expand Up @@ -85,3 +83,7 @@ const txResponse = await signer.sendTransaction({
feeCurrency: stableTokenAddress,
})
```

## Examples

See the tests under `/test` for more detailed examples.
9 changes: 6 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@celo-tools/celo-ethers-wrapper",
"version": "0.2.0",
"version": "0.3.0",
"description": "A minimal wrapper to make Ethers.JS compatible with the Celo network.",
"main": "build/main/index.js",
"typings": "build/main/index.d.ts",
Expand All @@ -13,18 +13,21 @@
"Ethers"
],
"scripts": {
"clean": "rm -rf build",
"build": "yarn build:main && yarn build:module",
"build:main": "tsc -p tsconfig.json",
"build:module": "tsc -p tsconfig.module.json",
"clean": "rm -rf build"
"test:contract": "ts-node test/useContract.ts",
"test:deploy": "ts-node test/deployContract.ts"
},
"engines": {
"node": ">=10"
},
"dependencies": {},
"devDependencies": {
"@types/node": "^16.11.10",
"ethers": "^5.5.1",
"ethers": "^5.6.8",
"ts-node": "^10.8.1",
"typescript": "^4.5.2"
},
"peerDependencies": {
Expand Down
16 changes: 15 additions & 1 deletion src/lib/CeloWallet.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { BigNumber, providers, utils, Wallet } from "ethers";
import { BigNumber, providers, utils, Wallet, Wordlist } from "ethers";
import type { CeloProvider } from "./CeloProvider";
import {
CeloTransactionRequest,
serializeCeloTransaction,
Expand Down Expand Up @@ -126,4 +127,17 @@ export class CeloWallet extends Wallet {
// @ts-ignore
return await this.provider.getGasPrice(feeCurrencyAddress);
}

connect(provider: CeloProvider): CeloWallet {
return new CeloWallet(this, provider);
}

static fromMnemonic(
mnemonic: string,
path?: string,
wordlist?: Wordlist
): CeloWallet {
const wallet = super.fromMnemonic(mnemonic, path, wordlist);
return new CeloWallet(wallet);
}
}
8 changes: 6 additions & 2 deletions src/lib/transactions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ export function serializeCeloTransaction(
return utils.RLP.encode(raw);
}

// Almost identical to https://github.com/ethers-io/ethers.js/blob/master/packages/transactions/src.ts/index.ts#L165
// Based on https://github.com/ethers-io/ethers.js/blob/0234cfbbef76b7f7a53efe4c434cc6d8892bf404/packages/transactions/src.ts/index.ts#L165
// Need to override to use the celo tx prop whitelists above
export function parseCeloTransaction(
rawTransaction: utils.BytesLike
Expand Down Expand Up @@ -262,7 +262,11 @@ function handleAddress(value: string): string | undefined {
if (value === "0x") {
return undefined;
}
return utils.getAddress(value);
try {
return utils.getAddress(value);
} catch (error) {
return value;
}
}

function handleNumber(value: string): BigNumber {
Expand Down
644 changes: 644 additions & 0 deletions test/HelloWorld.json

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions test/consts.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export const ALFAJORES_FORNO = "https://alfajores-forno.celo-testnet.org";
export const CELO_DERIVATION_PATH = "m/44'/52752'/0'/0/0";
export const HELLO_WORLD_ADDRESS = "0x21F637331830096a1fc6115c3dB9382fef4343Bf";
export const CUSD_ADDRESS = "0x874069Fa1Eb16D44d622F2e0Ca25eeA172369bC1";
25 changes: 25 additions & 0 deletions test/deployContract.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { ContractFactory } from "ethers";
import HelloWorldContract from "./HelloWorld.json";
import { getSigner } from "./utils";

async function main() {
const signer = getSigner();
console.info("Deploying to Alfajores with account", signer.address);
const factory = new ContractFactory(
HelloWorldContract.abi,
HelloWorldContract.bytecode,
signer
);
const contract = await factory.deploy();
await contract.deployTransaction.wait();
console.info("Contract deployed, address:", contract.address);

console.info("Sending tx to contract");
const txResponse = await contract.setName("myName");
const txReceipt = await txResponse.wait();
console.info("tx sent, hash:", txReceipt.transactionHash);
}

main()
.then(() => console.info("Deployment complete"))
.catch(console.error);
3 changes: 3 additions & 0 deletions test/stableToken.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export const STABLE_TOKEN_ABI = JSON.parse(
'[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"factor","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"lastUpdated","type":"uint256"}],"name":"InflationFactorUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"rate","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"updatePeriod","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"lastUpdated","type":"uint256"}],"name":"InflationParametersUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"registryAddress","type":"address"}],"name":"RegistrySet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"comment","type":"string"}],"name":"TransferComment","type":"event"},{"constant":true,"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"bytes","name":"blsKey","type":"bytes"},{"internalType":"bytes","name":"blsPop","type":"bytes"}],"name":"checkProofOfPossession","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"aNumerator","type":"uint256"},{"internalType":"uint256","name":"aDenominator","type":"uint256"},{"internalType":"uint256","name":"bNumerator","type":"uint256"},{"internalType":"uint256","name":"bDenominator","type":"uint256"},{"internalType":"uint256","name":"exponent","type":"uint256"},{"internalType":"uint256","name":"_decimals","type":"uint256"}],"name":"fractionMulExp","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes","name":"header","type":"bytes"}],"name":"getBlockNumberFromHeader","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getEpochNumber","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"blockNumber","type":"uint256"}],"name":"getEpochNumberOfBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getEpochSize","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"blockNumber","type":"uint256"}],"name":"getParentSealBitmap","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes","name":"header","type":"bytes"}],"name":"getVerifiedSealBitmapFromHeader","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes","name":"header","type":"bytes"}],"name":"hashHeader","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"initialized","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"isOwner","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"blockNumber","type":"uint256"}],"name":"minQuorumSize","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"minQuorumSizeInCurrentSet","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"numberValidatorsInCurrentSet","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"blockNumber","type":"uint256"}],"name":"numberValidatorsInSet","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"registry","outputs":[{"internalType":"contract IRegistry","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"renounceOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"registryAddress","type":"address"}],"name":"setRegistry","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"validatorSignerAddressFromCurrentSet","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"uint256","name":"blockNumber","type":"uint256"}],"name":"validatorSignerAddressFromSet","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getVersionNumber","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":false,"inputs":[{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_symbol","type":"string"},{"internalType":"uint8","name":"_decimals","type":"uint8"},{"internalType":"address","name":"registryAddress","type":"address"},{"internalType":"uint256","name":"inflationRate","type":"uint256"},{"internalType":"uint256","name":"inflationFactorUpdatePeriod","type":"uint256"},{"internalType":"address[]","name":"initialBalanceAddresses","type":"address[]"},{"internalType":"uint256[]","name":"initialBalanceValues","type":"uint256[]"}],"name":"initialize","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"rate","type":"uint256"},{"internalType":"uint256","name":"updatePeriod","type":"uint256"}],"name":"setInflationParameters","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"mint","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"string","name":"comment","type":"string"}],"name":"transferWithComment","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"value","type":"uint256"}],"name":"burn","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"accountOwner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"accountOwner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getInflationParameters","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"value","type":"uint256"}],"name":"valueToUnits","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"units","type":"uint256"}],"name":"unitsToValue","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"debitGasFees","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"feeRecipient","type":"address"},{"internalType":"address","name":"gatewayFeeRecipient","type":"address"},{"internalType":"address","name":"communityFund","type":"address"},{"internalType":"uint256","name":"refund","type":"uint256"},{"internalType":"uint256","name":"tipTxFee","type":"uint256"},{"internalType":"uint256","name":"gatewayFee","type":"uint256"},{"internalType":"uint256","name":"baseTxFee","type":"uint256"}],"name":"creditGasFees","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}]'
);
44 changes: 44 additions & 0 deletions test/useContract.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { BigNumber, Contract } from "ethers";
import { CUSD_ADDRESS } from "./consts";
import { STABLE_TOKEN_ABI } from "./stableToken";
import { getSigner } from "./utils";

async function main() {
const signer = getSigner();
console.info("Getting account balance for:", signer.address);
const balance = await signer.getBalance();
console.info("Balance:", balance.toString());

console.info("Sending 1 CELO wei", signer.address);
const txResponse1 = await signer.sendTransaction({
to: signer.address,
value: BigNumber.from("1"),
});
// Or, alternatively, break apart signing and sending:
// const signedTx = await signer.signTransaction({
// to: signer.address,
// value: BigNumber.from("1"),
// });
// const provider = signer.provider;
// const txResponse1 = await provider.sendTransaction(signedTx);
const txReceipt1 = await txResponse1.wait();
console.info("Funds sent. Hash:", txReceipt1.transactionHash);

const stableToken = new Contract(CUSD_ADDRESS, STABLE_TOKEN_ABI, signer);

console.info("Getting cUSD balance");
const stableBalance = await stableToken.balanceOf(signer.address);
console.info(`cUSD balance: ${stableBalance.toString()}`);

console.info("Sending 1 cUSD wei");
const txResponse2 = await stableToken.transfer(
signer.address,
BigNumber.from("1")
);
const txReceipt2 = await txResponse2.wait();
console.info(`cUSD payment hash: ${txReceipt2.transactionHash}`);
}

main()
.then(() => console.info("Contract tests complete"))
.catch(console.error);
16 changes: 16 additions & 0 deletions test/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { CeloProvider } from "../src/lib/CeloProvider";
import { CeloWallet } from "../src/lib/CeloWallet";
import { ALFAJORES_FORNO, CELO_DERIVATION_PATH } from "./consts";

export function getSigner() {
console.info("Getting signer");
const provider = new CeloProvider(ALFAJORES_FORNO);
const mnemonic = process.env.MNEMONIC;
if (!mnemonic) throw new Error("No MNEMONIC provided in env");
const wallet = CeloWallet.fromMnemonic(
mnemonic,
CELO_DERIVATION_PATH
).connect(provider);
console.info("Signer and provider ready");
return wallet;
}
Loading

0 comments on commit f4163a5

Please sign in to comment.