Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: USDC support as first-class citizen #130

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
"test": "TZ=UTC yarn jest --runInBand"
},
"dependencies": {
"@celo/abis": "10.0.0",
"@celo/abis": "canary",
"@celo/base": "^6.0.0",
"@celo/connect": "^5.1.1",
"@celo/contractkit": "^6.0.1-beta.0",
Expand Down
28 changes: 28 additions & 0 deletions packages/cli/src/commands/exchange/$usdc.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { StableToken } from '@celo/contractkit'
import ExchangeStableBase from '../../exchange-stable-base'
import { CustomFlags } from '../../utils/command'
export default class ExchangeReals extends ExchangeStableBase {
static description = 'Exchange Circle USD Coin ($USDC) for CELO via the stability mechanism'

static flags = {
...ExchangeStableBase.flags,
from: CustomFlags.address({
required: true,
description: 'The address with Circle USD Coin ($USDC) to exchange',
}),
value: CustomFlags.wei({
required: true,
description: 'The value of Circle USD Coin ($USDC) to exchange for CELO',
}),
}

static examples = [
'reals --value 10000000000000 --from 0xc1912fEE45d61C87Cc5EA59DaE31190FFFFf232d',
'reals --value 10000000000000 --forAtLeast 50000000000000 --from 0xc1912fEE45d61C87Cc5EA59DaE31190FFFFf232d',
]

async init() {
this._stableCurrency = StableToken.$USDC
await super.init()
}
}
1 change: 1 addition & 0 deletions packages/cli/src/commands/network/contracts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ const UNVERSIONED_CONTRACTS = [
CeloContract.StableToken,
CeloContract.StableTokenBRL,
CeloContract.StableTokenEUR,
CeloContract.StableToken$USDC,
]
const UNPROXIED_CONTRACTS: CeloContract[] = []

Expand Down
19 changes: 19 additions & 0 deletions packages/cli/src/commands/transfer/$usdc.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { StableToken } from '@celo/contractkit'
import { TransferStableBase } from '../../transfer-stable-base'

export default class TransferUSDCoin extends TransferStableBase {
static description = 'Transfer Circle USD Coin ($USDC) to a specified address.'

static flags = {
...TransferStableBase.flags,
}

static examples = [
'$usdc --from 0xa0Af2E71cECc248f4a7fD606F203467B500Dd53B --to 0x5409ed021d9299bf6814279a6a1411a7e866a631 --value 1000000000000000000',
]

async init() {
this._stableCurrency = StableToken.$USDC
await super.init()
}
}
2 changes: 1 addition & 1 deletion packages/cli/src/commands/transfer/reals.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { StableToken } from '@celo/contractkit'
import { TransferStableBase } from '../../transfer-stable-base'

export default class TransferEuros extends TransferStableBase {
export default class TransferReals extends TransferStableBase {
static description = 'Transfer Celo Brazilian Real (cREAL) to a specified address.'

static flags = {
Expand Down
10 changes: 6 additions & 4 deletions packages/sdk/base/README.MD
Original file line number Diff line number Diff line change
@@ -1,24 +1,26 @@

# @celo/base

This package contains shared classes and functions used by other celo packages. It was designed to have minimal external dependencies. (for shared celo functions that have big external dependencies see the @celo/utils, @celo/cryptographic-utils, @celo/phone-utils, @celo/network-utils packages)


## Notable Types

```typescript
// enums StableTokens and Token are enums, CeloTokenType is the type that must be one of the 2 enums
import { StableTokens, Token, CeloTokenType } from "@celo/base"
import { StableTokens, Token, CeloTokenType } from '@celo/base'

StableTokens.cUSD

StableTokens.cEUR

StableTokens.cREAL

StableTokens.$USDC

Token.CELO
```

## Notable Functions

```typescript
import { eqAddress, normalizeAddress, isNullAddress } from "@celo/base"
import { eqAddress, normalizeAddress, isNullAddress } from '@celo/base'
```
9 changes: 9 additions & 0 deletions packages/sdk/base/src/currencies.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@ export enum CURRENCY_ENUM {
GOLD = 'Celo Gold',
DOLLAR = 'Celo Dollar',
EURO = 'Celo Euro',
$USDC = 'USD Coin',
}

export enum StableToken {
cUSD = 'cUSD',
cEUR = 'cEUR',
cREAL = 'cREAL',
$USDC = '$USDC',
}

export enum Token {
Expand Down Expand Up @@ -42,6 +44,12 @@ export const CURRENCIES: CurrencyObject = {
code: 'cEUR',
displayDecimals: 2,
},
// NOTE: should we just get rid of CURRENCIES
[CURRENCY_ENUM.$USDC]: {
symbol: '$',
code: 'USDC',
displayDecimals: 2,
},
}

export const resolveCurrency = (label: string): CURRENCY_ENUM => {
Expand All @@ -57,6 +65,7 @@ export const resolveCurrency = (label: string): CURRENCY_ENUM => {
}
}

// NOTE: should we just get rid of SHORT_CURRENCIES
/** @deprecated use StableToken and Token */
export enum SHORT_CURRENCIES {
DOLLAR = 'dollar',
Expand Down
7 changes: 3 additions & 4 deletions packages/sdk/contractkit/MIGRATION-TO-ETHERS.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,10 +73,9 @@ async function getToken(token: string) {
}
async function CeloTokens(): Promise<[string, string][]> {
return Promise.all(
['GoldToken', 'StableToken', 'StableTokenEUR', 'StableTokenBRL'].map(async (token) => [
token,
await getToken(token),
])
['GoldToken', 'StableToken', 'StableTokenEUR', 'StableTokenBRL', 'StableToken$USDC'].map(
async (token) => [token, await getToken(token)]
)
)
}
```
Expand Down
41 changes: 20 additions & 21 deletions packages/sdk/contractkit/MIGRATION-TO-VIEM.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,10 +111,9 @@ const registryContract = getContract({

async function CeloTokens(): Promise<[string, string][]> {
return Promise.all(
['GoldToken', 'StableToken', 'StableTokenEUR', 'StableTokenBRL'].map(async (token) => [
token,
await registryContract.read.getAddressForString(token),
])
['GoldToken', 'StableToken', 'StableTokenEUR', 'StableTokenBRL', 'StableToken$USDC'].map(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I'm not mistaken, this is not going to work for StableToken$USDC, because USDC will not be a core contract, so won't be in Registry.sol.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

righto

async (token) => [token, await registryContract.read.getAddressForString(token)]
)
)
}
```
Expand Down Expand Up @@ -200,28 +199,28 @@ const stages = (await publicClient.multicall({ contracts: stageCalls })).map((x)
With Viem's built in Celo transaction serializer and Celo block/transaction formatters it is easy to build a wallet that supports Celo's ability to pay gas fees with various erc20 tokens. Simply, import a Celo chain from `viem/chain` and pass it to Viem's `createWalletClient`. Once the client is created you can add the feeCurrency field to your transaction with the address of the token you want to use for gas.

```ts
import { celo } from 'viem/chains'
import { createWalletClient, privateKeyToAccount, type SendTransactionParameters, http } from 'viem'
import { celo } from 'viem/chains'
import { createWalletClient, privateKeyToAccount, type SendTransactionParameters, http } from 'viem'

const account = privateKeyToAccount(PRIVATE_KEY)
const account = privateKeyToAccount(PRIVATE_KEY)

// ALFAJORES ADDRESS: Celo Mainnet can be fetched from the registry
const cUSDAddress = '0x874069Fa1Eb16D44d622F2e0Ca25eeA172369bC1'
// ALFAJORES ADDRESS: Celo Mainnet can be fetched from the registry
const cUSDAddress = '0x874069Fa1Eb16D44d622F2e0Ca25eeA172369bC1'

const localAccountClient = createWalletClient({
account,
chain: celo,
})
const localAccountClient = createWalletClient({
account,
chain: celo,
})

const sendTransaction = (tx: SendTransactionParameters<typeof celo>) => {
return localAccountClient.sendTransaction(tx)
}
const sendTransaction = (tx: SendTransactionParameters<typeof celo>) => {
return localAccountClient.sendTransaction(tx)
}

const hash = await sendTransaction({
feeCurrency: cUSDAddress,
value: BigInt(100000000),
to: '0x22579CA45eE22E2E16dDF72D955D6cf4c767B0eF',
})
const hash = await sendTransaction({
feeCurrency: cUSDAddress,
value: BigInt(100000000),
to: '0x22579CA45eE22E2E16dDF72D955D6cf4c767B0eF',
})
```

### Further reading
Expand Down
24 changes: 8 additions & 16 deletions packages/sdk/contractkit/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,26 +43,22 @@ const kit = newKit('https://alfajores-forno.celo-testnet.org')
To access balances:

```ts
// returns an object with {lockedGold, pending, cUSD, cEUR, cREAL}
// returns an object with {lockedGold, pending, cUSD, cEUR, cREAL, $USDC}

const balances = await kit.getTotalBalance()

// returns an object with {cUSD, cEUR, cREAL}
// returns an object with {cUSD, cEUR, cREAL, $USDC}
const balances = await miniKit.getTotalBalance()

```

If you don't need the balances of all tokens use the balanceOf method
```ts

```ts
const stableTokenWrapper = await kit.getStableToken(StableToken.cREAL)

const cRealBalance = stableTokenWrapper.balanceOf(accountAddress)

```



### Setting Default Tx Options

`kit` allows you to set default transaction options:
Expand Down Expand Up @@ -107,7 +103,7 @@ To send funds:
```ts
const oneGold = kit.connection.web3.utils.toWei('1', 'ether')
const tx = await goldToken.transfer(someAddress, oneGold).send({
from: myAddress
from: myAddress,
})

const hash = await tx.getHash()
Expand All @@ -117,7 +113,6 @@ const receipt = await tx.waitReceipt()
If you would like to pay fees in cUSD, (or other cStables like cEUR, cUSD).

```ts

kit.setFeeCurrency(CeloContract.StableToken) // Default to paying fees in cUSD

const stableTokenContract = kit.contracts.getStableToken()
Expand All @@ -129,7 +124,6 @@ const tx = await stableTokenContract
const hash = await tx.getHash()

const receipt = await tx.waitReceipt()

```

### Interacting with Core Contracts
Expand Down Expand Up @@ -162,8 +156,7 @@ When using the `kit` you can access core contracts like

`kit.contracts.get{ContractName}`

E.G. `kit.contracts.getAccounts()`, `kit.contracts.getValidators()`

E.G. `kit.contracts.getAccounts()`, `kit.contracts.getValidators()`

#### Stand Alone Wrappers

Expand All @@ -172,12 +165,11 @@ You can also initialize contracts wrappers directly. They require a `Connection`
```typescript
// MiniContractKit only gives access to a limited set of Contracts, so we import Multisig

import { newKit } from "@celo/contractkit/lib/mini-kit"
import { newKit } from '@celo/contractkit/lib/mini-kit'
import { MultiSigWrapper } from '@celo/contractkit/lib/wrappers/MultiSig'
import { newMultiSig } from '@celo/abis/web3/MultiSig'


const miniKit = newKit("https://alfajores-forno.celo-testnet.org/")
const miniKit = newKit('https://alfajores-forno.celo-testnet.org/')

// Alternatively import { Connection } from '@celo/connect'
// const connection = new Connection(web3)
Expand All @@ -189,7 +181,7 @@ const multisigWrapper = new MultiSigWrapper(miniKit.connection, contract)

### Accessing web3 contract wrappers

`MiniContractKit` *does not provide access to the web3 contracts*
`MiniContractKit` _does not provide access to the web3 contracts_

Some user might want to access web3 native contract wrappers.

Expand Down
2 changes: 1 addition & 1 deletion packages/sdk/contractkit/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
"lint": "yarn run --top-level eslint -c .eslintrc.js "
},
"dependencies": {
"@celo/abis": "10.0.0",
"@celo/abis": "canary",
"@celo/base": "^6.0.0",
"@celo/connect": "^5.1.1",
"@celo/utils": "^5.0.6",
Expand Down
2 changes: 2 additions & 0 deletions packages/sdk/contractkit/src/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,15 @@ export enum CeloContract {
StableToken = 'StableToken',
StableTokenEUR = 'StableTokenEUR',
StableTokenBRL = 'StableTokenBRL',
StableToken$USDC = 'StableToken$USDC',
Validators = 'Validators',
}

export type StableTokenContract =
| CeloContract.StableToken
| CeloContract.StableTokenEUR
| CeloContract.StableTokenBRL
| CeloContract.StableToken$USDC

export type CeloTokenContract = StableTokenContract | CeloContract.GoldToken
/**
Expand Down
4 changes: 4 additions & 0 deletions packages/sdk/contractkit/src/celo-tokens.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ export const stableTokenInfos: {
contract: CeloContract.StableTokenBRL,
symbol: StableToken.cREAL,
},
[StableToken.$USDC]: {
contract: CeloContract.StableToken$USDC,
symbol: StableToken.$USDC,
},
}

/** Basic info for each supported celo token, including stable tokens */
Expand Down
6 changes: 6 additions & 0 deletions packages/sdk/contractkit/src/contract-cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ const WrapperFactories = {
[CeloContract.StableToken]: StableTokenWrapper,
[CeloContract.StableTokenEUR]: StableTokenWrapper,
[CeloContract.StableTokenBRL]: StableTokenWrapper,
// TODO: use the TokenAdapter from @celo/abis@11 when it's out
// https://docs.celo.org/protocol/transaction/erc20-transaction-fees#alfajores-testnet
[CeloContract.StableToken$USDC]: StableTokenWrapper,
} as const

const WithRegistry = {
Expand Down Expand Up @@ -98,6 +101,9 @@ interface WrapperCacheMap {
[CeloContract.StableToken]?: StableTokenWrapper
[CeloContract.StableTokenEUR]?: StableTokenWrapper
[CeloContract.StableTokenBRL]?: StableTokenWrapper
// TODO: use the TokenAdapter from @celo/abis@11 when it's out
// https://docs.celo.org/protocol/transaction/erc20-transaction-fees#alfajores-testnet
[CeloContract.StableToken$USDC]?: StableTokenWrapper
[CeloContract.Validators]?: ValidatorsWrapper
}

Expand Down
7 changes: 7 additions & 0 deletions packages/sdk/contractkit/src/mini-contract-cache.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import {} from '@celo/abis'
import { newGasPriceMinimum } from '@celo/abis/web3/0.8/GasPriceMinimum'
import { newAccounts } from '@celo/abis/web3/Accounts'
import { newGoldToken } from '@celo/abis/web3/GoldToken'
Expand Down Expand Up @@ -40,6 +41,12 @@ const MINIMUM_CONTRACTS = {
newInstance: newStableTokenEUR,
wrapper: StableTokenWrapper,
},
[CeloContract.StableToken$USDC]: {
// TODO: use the TokenAdapter from @celo/abis@11 when it's out
// https://docs.celo.org/protocol/transaction/erc20-transaction-fees#alfajores-testnet
// newInstance: newStableToken$USDC,
wrapper: StableTokenWrapper,
},
}

export type ContractsBroughtBase = typeof MINIMUM_CONTRACTS
Expand Down
1 change: 1 addition & 0 deletions packages/sdk/contractkit/src/proxy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ const initializeAbiMap = {
StableTokenProxy: findInitializeAbi(StableTokenABI),
StableTokenEURProxy: findInitializeAbi(StableTokenABI),
StableTokenBRLProxy: findInitializeAbi(StableTokenABI),
StableToken$USDCProxy: findInitializeAbi(StableTokenABI),
ValidatorsProxy: findInitializeAbi(ValidatorsABI),
}

Expand Down
Loading
Loading