Skip to content

Commit

Permalink
Merge pull request #432 from trustlines-protocol/update_eip1559
Browse files Browse the repository at this point in the history
Try to make test pass with EIP1559
  • Loading branch information
compojoom authored Nov 23, 2022
2 parents 06004a3 + 7611423 commit f78655c
Show file tree
Hide file tree
Showing 31 changed files with 3,131 additions and 272 deletions.
2 changes: 2 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ COPY --from=builder /usr/local/bin/yarn /usr/local/bin/yarn
COPY --from=builder /usr/local/lib/node_modules /usr/local/lib/node_modules
COPY --from=builder /clientlib /clientlib

ENV RPC_PROVIDER_URL="http://node:8545"
ENV SAFE_RELAY_PROVIDER_URL="http://nginx:8000/api"
ENV RELAY_HOSTNAME relay
WORKDIR /clientlib
CMD ["yarn", "test:e2e"]
2 changes: 1 addition & 1 deletion filterContracts/filterContracts.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { writeFile } from 'fs'

const requiredContracts = ['CurrencyNetwork', 'Exchange', 'Identity', 'UnwEth']
const pathContractsModule =
'node_modules/trustlines-contracts-abi/contracts.json'
'node_modules/@trustlines/trustlines-contracts-abi/contracts.json'

const filteredAbi = Object.fromEntries(
Object.entries(TrustlinesContractsAbi['default']).filter(([key, value]) =>
Expand Down
7 changes: 4 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"prettier:check": "prettier --check './{src,tests}/**/*.ts'",
"prettier:big-tabs": "prettier --write --print-width 120 --no-semi --single-quote --tab-width 4 './{src,tests}/**/*.ts'",
"test": "mocha --timeout 30000 --require isomorphic-fetch -r ts-node/register tests/**/**.test.ts",
"test:e2e": "nyc mocha --timeout 30000 --require isomorphic-fetch -r ts-node/register tests/e2e/**.test.ts",
"test:e2e": "nyc mocha --timeout 240000 --require isomorphic-fetch -r ts-node/register tests/e2e/**.test.ts",
"test:integration": "nyc mocha --timeout 5000 --require isomorphic-fetch -r ts-node/register tests/integration/**.test.ts",
"test:unit": "nyc mocha --timeout 30000 --require isomorphic-fetch -r ts-node/register tests/unit/**.test.ts",
"coverage": "nyc report --reporter=text-lcov > coverage.lcov && codecov",
Expand Down Expand Up @@ -69,7 +69,7 @@
"awesome-typescript-loader": "^5.2.0",
"chai": "^4.1.2",
"chai-as-promised": "^7.1.1",
"codecov": "^3.5.0",
"codecov": "^3.8.3",
"es6-promise": "^4.1.1",
"fetch-mock": "^7.2.5",
"fluid-publish": "^2.2.0",
Expand All @@ -90,11 +90,12 @@
"webpack-cli": "^3.0.8"
},
"dependencies": {
"@gnosis.pm/safe-core-sdk": "^3.1.1",
"@msgpack/msgpack": "^1.12.1",
"@trustlines/trustlines-contracts-abi": "^2.0.0",
"bignumber.js": "7.2.1",
"ethereumjs-util": "^5.2.0",
"ethers": "^4.0.23",
"ethers": "5.7.1",
"reconnecting-websocket": "^4.1.10",
"rxjs": "^5.4.1",
"simple-jsonrpc-js": "0.0.10",
Expand Down
41 changes: 38 additions & 3 deletions src/TLNetwork.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,16 @@ import { EthersWallet } from './wallets/EthersWallet'
import {
TLWallet,
WALLET_TYPE_ETHERS,
WALLET_TYPE_IDENTITY
WALLET_TYPE_IDENTITY,
WALLET_TYPE_SAFE
} from './wallets/TLWallet'

import utils from './utils'

import { SafeRelayProvider } from './providers/SafeRelayProvider'
import { NonceMechanism, ProviderUrl, TLNetworkConfig } from './typings'
import { IdentityWallet } from './wallets/IdentityWallet'
import { SafeWallet } from './wallets/SafeWallet'

/**
* The TLNetwork class is the single entry-point into the trustlines-clientlib.
Expand Down Expand Up @@ -63,6 +66,7 @@ export class TLNetwork {
path: url.path || defaultUrlParameters.path
})
}

/**
* User instance containing all user/keystore related methods.
*/
Expand Down Expand Up @@ -128,6 +132,10 @@ export class TLNetwork {
* @hidden
*/
public messagingProvider: Provider
/**
* @hidden
*/
public safeRelayProvider: SafeRelayProvider

/**
* Initiates a new TLNetwork instance that provides the public interface to trustlines-clientlib.
Expand All @@ -137,9 +145,12 @@ export class TLNetwork {
const {
relayUrl = {},
messagingUrl = {},
safeRelayUrl = {},
web3Provider,
identityFactoryAddress,
identityImplementationAddress,
gnosisSafeL2Address,
gnosisSafeProxyFactoryAddress,
walletType = WALLET_TYPE_ETHERS,
chainId,
nonceMechanism = NonceMechanism.Random
Expand All @@ -160,15 +171,22 @@ export class TLNetwork {
new Provider(
TLNetwork.getApiUrl(messagingUrl, defaultUrlParameters),
TLNetwork.getWsUrl(messagingUrl, defaultUrlParameters)
),
new SafeRelayProvider(
TLNetwork.getApiUrl(safeRelayUrl, defaultUrlParameters),
TLNetwork.getWsUrl(safeRelayUrl, defaultUrlParameters)
)
)

this.setWallet(
walletType,
this.relayProvider,
this.safeRelayProvider,
chainId,
identityFactoryAddress,
identityImplementationAddress,
gnosisSafeL2Address,
gnosisSafeProxyFactoryAddress,
nonceMechanism
)
this.setSigner(web3Provider, this.wallet)
Expand Down Expand Up @@ -233,13 +251,15 @@ export class TLNetwork {
*/
public setProviders(
relayProvider: TLProvider,
messagingProvider: Provider
messagingProvider: Provider,
safeRelayProvider: SafeRelayProvider
): void {
if (!(relayProvider instanceof RelayProvider)) {
throw new Error('Provider not supported.')
}
this.relayProvider = relayProvider
this.messagingProvider = messagingProvider
this.safeRelayProvider = safeRelayProvider
}

/**
Expand All @@ -254,7 +274,8 @@ export class TLNetwork {
!(
signer instanceof Web3Signer ||
signer instanceof EthersWallet ||
signer instanceof IdentityWallet
signer instanceof IdentityWallet ||
signer instanceof SafeWallet
)
) {
throw new Error('Signer not supported.')
Expand All @@ -268,9 +289,12 @@ export class TLNetwork {
public setWallet(
walletType: string,
provider: TLProvider,
safeRelayProvider: SafeRelayProvider,
chainId: number,
identityFactoryAddress: string,
identityImplementationAddress: string,
gnosisSafeL2Address,
gnosisSafeProxyFactoryAddress,
nonceMechanism: NonceMechanism
): void {
let wallet: TLWallet
Expand All @@ -283,6 +307,17 @@ export class TLNetwork {
identityImplementationAddress,
nonceMechanism
)
} else if (walletType === WALLET_TYPE_SAFE) {
wallet = new SafeWallet(
provider,
safeRelayProvider,
chainId,
identityFactoryAddress,
identityImplementationAddress,
gnosisSafeL2Address,
gnosisSafeProxyFactoryAddress,
nonceMechanism
)
} else if (walletType === WALLET_TYPE_ETHERS) {
wallet = new EthersWallet(provider)
} else {
Expand Down
15 changes: 7 additions & 8 deletions src/Transaction.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { Interface } from '@ethersproject/abi'
import { AddressZero } from '@ethersproject/constants'
import { Logger } from '@ethersproject/logger'
import * as TrustlinesContractsAbi from '@trustlines/trustlines-contracts-abi'
import { BigNumber } from 'bignumber.js'
import { ethers } from 'ethers'
import { AddressZero } from 'ethers/constants'

import { TLProvider } from './providers/TLProvider'
import { TLSigner } from './signers/TLSigner'
Expand All @@ -22,12 +23,12 @@ import { CurrencyNetwork } from './CurrencyNetwork'

// Ethers will otherwise warn for every call on `updateTrustline` due to function overloading
// see https://github.com/ethers-io/ethers.js/issues/407
ethers.errors.setLogLevel('error')
Logger.setLogLevel(Logger.levels.ERROR)

const ETH_DECIMALS = 18
export const GAS_LIMIT_MULTIPLIER = 1.2
// Value taken from the contracts gas tests
export const GAS_LIMIT_IDENTITY_OVERHEAD = new BigNumber(27_000)
export const GAS_LIMIT_IDENTITY_OVERHEAD = new BigNumber(50_000)
export const GAS_LIMIT_VALUE_TRANSACTION = new BigNumber(21_000)
.plus(GAS_LIMIT_IDENTITY_OVERHEAD.multipliedBy(GAS_LIMIT_MULTIPLIER))
.integerValue(BigNumber.ROUND_DOWN)
Expand Down Expand Up @@ -73,11 +74,9 @@ export class Transaction {
args: any[],
options: TxOptionsInternal = {}
): Promise<TxObjectInternal> {
const abi = new ethers.utils.Interface(
TrustlinesContractsAbi[contractName].abi
)
const abi = new Interface(TrustlinesContractsAbi[contractName].abi)
const rawTx: RawTxObject = {
data: abi.functions[functionName].encode(args),
data: abi.encodeFunctionData(functionName, args),
from: userAddress,
to: contractAddress,
gasLimit: options.gasLimit || GAS_LIMIT_DEFAULT_CONTRACT_TRANSACTION,
Expand Down
2 changes: 1 addition & 1 deletion src/providers/Provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export class Provider {
public async postToEndpoint<T>(endpoint: string, data: any): Promise<T> {
const options = {
body: JSON.stringify(data),
headers: new Headers({ 'Content-Type': 'application/json' }),
headers: { 'Content-Type': 'application/json' },
method: 'POST'
}
return this.fetchEndpoint<T>(endpoint, options)
Expand Down
150 changes: 150 additions & 0 deletions src/providers/SafeRelayProvider.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
import { AddressZero } from '@ethersproject/constants'
import {
Amount,
EstimationResponse,
SafeMetaTransaction,
SafeMultisigTxResponse,
SafeTransactionFees,
TransactionStatus,
TransactionStatusObject
} from '../typings'
import utils from '../utils'
import { Provider } from './Provider'

export class SafeRelayProvider extends Provider {
public ApiUrl: string
public WsApiUrl: string

public async plainFetch(endpoint: string) {
const response = await fetch(`${this.ApiUrl}/${endpoint}`)
return response
}

/**
* Returns a JSON response from the REST API of the server.
*
* We overload this method since the safe relay server from gnosis doesn't like
* urls with a trimmed slash at the end.
*
* @param endpoint Endpoint to fetch.
* @param options Optional fetch options.
*/
public async fetchEndpoint<T>(
endpoint: string,
options?: object
): Promise<T> {
return utils.fetchUrl<T>(`${this.ApiUrl}/${endpoint}`, options)
}

public async getSafeNonce(safeAddress: string): Promise<number> {
const response = await this.plainFetch(`v1/safes/${safeAddress}/`)

if (response.status === 200) {
const json = await response.json()
return json.nonce
}

throw new Error(`Error fetching safe nonce: ${response.status}`)
}

/**
* Returns the fees the provider would be willing to pay for the transaction
* @param metaTransaction Meta transaction to be relayed
* @returns The fees value and currency network of fees for given meta transaction
*/
public async getMetaTxFees(
metaTransaction: SafeMetaTransaction
): Promise<SafeTransactionFees> {
const data = {
safe: metaTransaction.safe,
to: metaTransaction.to,
value: metaTransaction.value,
data: metaTransaction.data,
operation: metaTransaction.operation
}

const response: EstimationResponse = await this.postToEndpoint(
`v2/safes/${metaTransaction.safe}/transactions/estimate/`,
data
)

return {
safeTxGas: response.safeTxGas,
baseGas: response.baseGas,
gasPrice: response.gasPrice,
refundReceiver: response.refundReceiver,
gasToken: response.gasToken || AddressZero
}
}

/**
* Send the given signed meta-transaction to a relay server to execute it on the
* blockchain and returns a `Promise` with the transaction hash.
* @param signedMetaTransaction Signed meta-transaction to be sent to the relay server
* @returns The hash of the transaction sent by the relay server, not to be confused with the hash of the meta-transaction
*/
public async sendSignedMetaTransaction(
signedMetaTransaction: SafeMetaTransaction
): Promise<any> {
const response: any = await this.postToEndpoint(
`v1/safes/${signedMetaTransaction.safe}/transactions/`,
signedMetaTransaction
)

return response.txHash
}

/**
* Returns implementation address of identity with given address
* @param address Address of identity
* @returns the implementation address currently in use by the given identity
*/
public async getIdentityImplementationAddress(
address: string
): Promise<string> {
const { masterCopy } = await this.fetchEndpoint<any>(`v1/safes/${address}`)
return masterCopy
}

public async getMetaTxStatus(
safeAddress: string,
transactionHash: string
): Promise<TransactionStatusObject> {
try {
const response: SafeMultisigTxResponse = await this.fetchEndpoint(
`/v1/safes/${safeAddress}/transactions/?safe_tx_hash=${transactionHash}`
)

if (response.results.length) {
const tx = response.results[0]
const status = tx.metaTxSuccessful
return {
status: status ? TransactionStatus.Success : TransactionStatus.Failure
}
}
} catch (e) {
if (e.message.includes('Status 404')) {
return { status: TransactionStatus.NotFound }
}
return { status: TransactionStatus.Failure }
}
}

/**
* Returns balance of given address.
* @param address Address to determine balance for.
*/
public async getBalance(address: string): Promise<Amount> {
// return utils.formatToAmount(0, 18)
try {
const response: Array<{
tokenAddress: string | null
balance: string
}> = await this.fetchEndpoint(`/v1/safes/${address}/balances`)

return utils.formatToAmount(response[0].balance, 18)
} catch (e) {
return utils.formatToAmount(0, 18)
}
}
}
5 changes: 4 additions & 1 deletion src/signers/TLSigner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {
Amount,
MetaTransactionFees,
RawTxObject,
SafeTransactionFees,
Signature,
TransactionStatusObject,
TxObjectRaw
Expand All @@ -19,5 +20,7 @@ export interface TLSigner {
confirm(rawTx: RawTxObject): Promise<string>
prepareTransaction(rawTx: RawTxObject): Promise<TxObjectRaw>
getTxStatus(txHash: string | RawTxObject): Promise<TransactionStatusObject>
getMetaTxFees(rawTx: RawTxObject): Promise<MetaTransactionFees>
getMetaTxFees(
rawTx: RawTxObject
): Promise<MetaTransactionFees | SafeTransactionFees>
}
Loading

0 comments on commit f78655c

Please sign in to comment.