Skip to content

Commit

Permalink
New ContractKit (#480)
Browse files Browse the repository at this point in the history
Implemented features:

-yarn build on protocol generates code for contractkit
-cleanup protocol build
-yarn build on root pkg breaks if contractkit doesn't compile with generated code
-Fetch addresses from registry (only once)
-Expose all web3 contract wrappers & cache them
-Framework to create wrappers
-Celo Wrappers for BondedDeposits, Exchange, Validators, GoldToken, StableToken
-Contract kit is instantiable, can have many instances in one process
-sendTransaction ported from walletkit

Missing: Test, complete Wrappers, validate API

Other changes
 -Cleanup protocol build process.
 - Fix celo/utils npm publish
 - hoist ts-node to the root package
 - Related issues

Fixes #360 #359 #333 #257
  • Loading branch information
Mariano Cortesi authored Aug 16, 2019
1 parent e36614d commit 4fa6d7b
Show file tree
Hide file tree
Showing 46 changed files with 1,156 additions and 97 deletions.
2 changes: 2 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ packages/blockchain-api/dist

packages/cli/lib

packages/contractkit/lib/

packages/walletkit/lib/
packages/walletkit/.artifacts/
packages/walletkit/contracts/
Expand Down
8 changes: 7 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,14 +44,20 @@
]
},
"devDependencies": {
"@types/jest": "^24.0.13",
"husky": "^3.0.0",
"lerna": "^3.16.0",
"patch-package": "^5.1.1",
"prettier": "1.13.5",
"pretty-quick": "^1.11.1",
"solc": "0.5.8",
"tslint": "^5.12.1",
"typescript-tslint-plugin": "^0.5.0"
"typescript": "^3.3.3",
"jest": "^24.8.0",
"ts-jest": "^24.0.0",
"typescript-tslint-plugin": "^0.5.0",
"tsconfig-paths": "^3.8.0",
"ts-node": "^8"
},
"dependencies": {
"codecov": "^3.1.0"
Expand Down
3 changes: 1 addition & 2 deletions packages/celotool/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,7 @@
"@types/web3": "^1.0.18",
"@types/yargs": "^12.0.1",
"jest": "^24.8.0",
"ts-jest": "^24.0.0",
"ts-node": "^7.0.1"
"ts-jest": "^24.0.0"
},
"scripts": {
"cli": "TS_NODE_FILES=true ts-node -r tsconfig-paths/register src/cli.ts",
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@
"@types/node": "^10",
"@types/web3": "^1.0.18",
"globby": "^8",
"ts-node": "^8",

"tslint": "^5",
"typescript": "^3.3.3"
},
Expand Down
17 changes: 12 additions & 5 deletions packages/cli/src/adapters/bonded-deposit.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import { BondedDeposits } from '@celo/walletkit'
import BN from 'bn.js'
import Web3 from 'web3'
import { TransactionObject } from 'web3/eth/types'

import { BondedDeposits } from '@celo/walletkit'

import { Address, zip } from '../utils/helpers'

export interface VotingDetails {
Expand All @@ -25,6 +23,13 @@ export interface Deposits {
weight: BN
}
}

enum Roles {
validating,
voting,
rewards,
}

export class BondedDepositAdapter {
public contractPromise: ReturnType<typeof BondedDeposits>

Expand All @@ -45,7 +50,9 @@ export class BondedDepositAdapter {
async getVotingDetails(accountOrVoterAddress: Address): Promise<VotingDetails> {
const contract = await this.contract()

const accountAddress = await contract.methods.getAccountFromVoter(accountOrVoterAddress).call()
const accountAddress = await contract.methods
.getAccountFromDelegateAndRole(accountOrVoterAddress, Roles.voting)
.call()

return {
accountAddress,
Expand Down Expand Up @@ -124,7 +131,7 @@ export class BondedDepositAdapter {
const contract = await this.contract()
const sig = await this.getParsedSignatureOfAddress(account, delegate)

return contract.methods.delegateRewards(delegate, sig.v, sig.r, sig.s)
return contract.methods.delegateRole(Roles.rewards, delegate, sig.v, sig.r, sig.s)
}

async getParsedSignatureOfAddress(address: string, signer: string) {
Expand Down
3 changes: 3 additions & 0 deletions packages/contractkit/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
src/generated
tsconfig.tsbuildinfo
lib/
7 changes: 7 additions & 0 deletions packages/contractkit/.npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/node_modules
/coverage
/tslint.json
/tsconfig.json
/test
/src
/jest.config.json
7 changes: 7 additions & 0 deletions packages/contractkit/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module.exports = {
preset: 'ts-jest',
testEnvironment: 'node',
moduleNameMapper: {
'^src/(.*)$': '<rootDir>/src/$1',
},
}
38 changes: 38 additions & 0 deletions packages/contractkit/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{
"name": "@celo/contractkit",
"version": "0.0.5-beta3",
"description": "Celo's ContractKit to interact with Celo network",
"main": "./lib/index.js",
"types": "./lib/index.d.ts",
"author": "Celo",
"license": "Apache-2.0",
"homepage": "https://github.com/celo-org/celo-monorepo/tree/master/packages/contractkit",
"repository": "https://github.com/celo-org/celo-monorepo/tree/master/packages/contractkit",
"keywords": ["celo", "blockchain", "contractkit", "defi"],
"scripts": {
"build": "tsc -b .",
"clean": "tsc -b . --clean && rm -rf src/generated",
"build:gen": "yarn --cwd ../protocol build",
"prepublishOnly": "yarn build:gen && yarn build",
"lint": "tslint -c tslint.json --project . && tslint -c tslint.json --project test"
},
"dependencies": {
"@celo/utils": "^0.0.6-beta3",
"@types/debug": "^4.1.5",
"bignumber.js": "^7.2.0",
"debug": "^4.1.1",
"web3": "1.0.0-beta.37",
"web3-utils": "1.0.0-beta.37"
},
"devDependencies": {
"@celo/protocol": "1.0.0",
"@types/jest": "^24.0.13",
"@types/web3": "^1.0.18"
},
"engines": {
"node": ">=8.16.0"
},
"files": [
"lib/**/*"
]
}
37 changes: 37 additions & 0 deletions packages/contractkit/src/address-registry.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { Address, AllContracts, CeloContract, NULL_ADDRESS } from './base'
import { newRegistry } from './generated/Registry'
import { Registry } from './generated/types/Registry'
import { ContractKit } from './kit'

// Registry contract is always predeployed to this address
const REGISTRY_CONTRACT_ADDRESS = '0x000000000000000000000000000000000000ce10'

export class AddressRegistry {
private readonly registry: Registry
private readonly cache: Map<CeloContract, Address> = new Map()

constructor(kit: ContractKit) {
this.cache.set(CeloContract.Registry, REGISTRY_CONTRACT_ADDRESS)
this.registry = newRegistry(kit.web3, REGISTRY_CONTRACT_ADDRESS)
}

async addressFor(contract: CeloContract): Promise<Address> {
if (!this.cache.has(contract)) {
const address = await this.registry.methods.getAddressFor(contract).call()

if (!address || address === NULL_ADDRESS) {
throw new Error(`Failed to get address for ${contract} from the Registry`)
}
this.cache.set(contract, address)
}
return this.cache.get(contract)!
}

async allAddresses(): Promise<Record<CeloContract, Address>> {
const res: Partial<Record<CeloContract, Address>> = {}
for (const contract of AllContracts) {
res[contract] = await this.addressFor(contract)
}
return res as Record<CeloContract, Address>
}
}
27 changes: 27 additions & 0 deletions packages/contractkit/src/base.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
export type Address = string

export enum CeloContract {
Attestations = 'Attestations',
BondedDeposits = 'BondedDeposits',
Escrow = 'Escrow',
Exchange = 'Exchange',
GasCurrencyWhitelist = 'GasCurrencyWhitelist',
GasPriceMinimum = 'GasPriceMinimum',
GoldToken = 'GoldToken',
Governance = 'Governance',
MultiSig = 'MultiSig',
Random = 'Random',
Registry = 'Registry',
Reserve = 'Reserve',
SortedOracles = 'SortedOracles',
StableToken = 'StableToken',
Validators = 'Validators',
}

export type CeloToken = CeloContract.GoldToken | CeloContract.StableToken

export const AllContracts = Object.keys(CeloContract).map(
(k) => CeloContract[k as any]
) as CeloContract[]

export const NULL_ADDRESS = '0x0000000000000000000000000000000000000000' as Address
104 changes: 104 additions & 0 deletions packages/contractkit/src/contract-cache.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import { CeloContract } from './base'
import { ContractKit } from './kit'
import { BondedDepositsWrapper } from './wrappers/BondedDeposits'
import { ExchangeWrapper } from './wrappers/Exchange'
import { GoldTokenWrapper } from './wrappers/GoldTokenWrapper'
import { StableTokenWrapper } from './wrappers/StableTokenWrapper'
import { ValidatorsWrapper } from './wrappers/Validators'

const WrapperFactories = {
// [CeloContract.Attestations]: AttestationsWrapper,
[CeloContract.BondedDeposits]: BondedDepositsWrapper,
// [CeloContract.Escrow]: EscrowWrapper,
[CeloContract.Exchange]: ExchangeWrapper,
// [CeloContract.GasCurrencyWhitelist]: GasCurrencyWhitelistWrapper,
// [CeloContract.GasPriceMinimum]: GasPriceMinimumWrapper,
[CeloContract.GoldToken]: GoldTokenWrapper,
// [CeloContract.Governance]: GovernanceWrapper,
// [CeloContract.MultiSig]: MultiSigWrapper,
// [CeloContract.Random]: RandomWrapper,
// [CeloContract.Registry]: RegistryWrapper,
// [CeloContract.Reserve]: ReserveWrapper,
// [CeloContract.SortedOracles]: SortedOraclesWrapper,
[CeloContract.StableToken]: StableTokenWrapper,
[CeloContract.Validators]: ValidatorsWrapper,
}

type CFType = typeof WrapperFactories

interface WrapperCacheMap {
// [CeloContract.Attestations]?: AttestationsWrapper,
[CeloContract.BondedDeposits]?: BondedDepositsWrapper
// [CeloContract.Escrow]?: EscrowWrapper,
[CeloContract.Exchange]?: ExchangeWrapper
// [CeloContract.GasCurrencyWhitelist]?: GasCurrencyWhitelistWrapper,
// [CeloContract.GasPriceMinimum]?: GasPriceMinimumWrapper,
[CeloContract.GoldToken]?: GoldTokenWrapper
// [CeloContract.Governance]?: GovernanceWrapper,
// [CeloContract.MultiSig]?: MultiSigWrapper,
// [CeloContract.Random]?: RandomWrapper,
// [CeloContract.Registry]?: RegistryWrapper,
// [CeloContract.Reserve]?: ReserveWrapper,
// [CeloContract.SortedOracles]?: SortedOraclesWrapper,
[CeloContract.StableToken]?: StableTokenWrapper
[CeloContract.Validators]?: ValidatorsWrapper
}

export class WrapperCache {
// private wrapperCache: Map<CeloContract, any> = new Map()
private wrapperCache: WrapperCacheMap = {}

constructor(readonly kit: ContractKit) {}

// getAttestations() {
// return this.getWrapper(CeloContract.Attestations, newAttestations)
// }
getBondedDeposits() {
return this.getContract(CeloContract.BondedDeposits)
}
// getEscrow() {
// return this.getWrapper(CeloContract.Escrow, newEscrow)
// }
getExchange() {
return this.getContract(CeloContract.Exchange)
}
// getGasCurrencyWhitelist() {
// return this.getWrapper(CeloContract.GasCurrencyWhitelist, newGasCurrencyWhitelist)
// }
// getGasPriceMinimum() {
// return this.getWrapper(CeloContract.GasPriceMinimum, newGasPriceMinimum)
// }
getGoldToken() {
return this.getContract(CeloContract.GoldToken)
}
// getGovernance() {
// return this.getWrapper(CeloContract.Governance, newGovernance)
// }
// getMultiSig() {
// return this.getWrapper(CeloContract.MultiSig, newMultiSig)
// }
// getRegistry() {
// return this.getWrapper(CeloContract.Registry, newRegistry)
// }
// getReserve() {
// return this.getWrapper(CeloContract.Reserve, newReserve)
// }
// getSortedOracles() {
// return this.getWrapper(CeloContract.SortedOracles, newSortedOracles)
// }
getStableToken() {
return this.getContract(CeloContract.StableToken)
}
getValidators() {
return this.getContract(CeloContract.Validators)
}

public async getContract<C extends keyof CFType>(contract: C) {
if (this.wrapperCache[contract] == null) {
const instance = await this.kit._web3Contracts.getContract(contract)
const Klass: CFType[C] = WrapperFactories[contract]
this.wrapperCache[contract] = new Klass(this.kit, instance as any) as any
}
return this.wrapperCache[contract]!
}
}
8 changes: 8 additions & 0 deletions packages/contractkit/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import Web3 from 'web3'

export { Address, CeloContract, CeloToken, NULL_ADDRESS } from './base'
export * from './kit'

export function newWeb3(url: string) {
return new Web3(url)
}
Loading

0 comments on commit 4fa6d7b

Please sign in to comment.