2023.04.18: Check HISTORY.md for more info
Signed-off-by: T-Hax <>
This commit is contained in:
parent
0a7c98abb9
commit
d83dcd8112
1
.gitignore
vendored
1
.gitignore
vendored
@ -8,3 +8,4 @@ cache
|
||||
.env
|
||||
scripts
|
||||
reference
|
||||
.npm
|
||||
|
@ -1,4 +1,3 @@
|
||||
build
|
||||
node_modules
|
||||
package-log.json
|
||||
types/sol
|
12
HISTORY.md
12
HISTORY.md
@ -1,5 +1,17 @@
|
||||
# History
|
||||
|
||||
### 2023.04.18 (2023-04-18)
|
||||
|
||||
Did:
|
||||
|
||||
* Trying to test withdrawals. The issue is that the ganache provider seemingly can't provide data on events via queryFilter. Have manually inserted events, commitments seem to pass but the note is deemed invalid by the contract on forknet.
|
||||
* Tests are more complicated right now, they rely on synchronized caches. Per default, all but that withdraw one should pass.
|
||||
* The good news is, if we pass the withdraw test, then we almost have the hardest part done.
|
||||
|
||||
Next:
|
||||
|
||||
* Need to reorganize into monorepo.
|
||||
|
||||
### 2023.04.12 (2023-04-12)
|
||||
|
||||
Did:
|
||||
|
@ -10,7 +10,7 @@
|
||||
"zk"
|
||||
],
|
||||
"private": false,
|
||||
"version": "2023.04.12",
|
||||
"version": "2023.04.18",
|
||||
"engines": {
|
||||
"node": "^18"
|
||||
},
|
||||
@ -29,7 +29,8 @@
|
||||
"lint": "eslint --ext ts,js --fix src",
|
||||
"format": "prettier src/lib/**/*.ts src/types/sdk/**/*.ts src/test/**/*.ts -w",
|
||||
"build-live": "tsc -w && tsc-alias -w",
|
||||
"typechain": "typechain --target \"ethers-v5\" --discriminate-types --glob \"./src/resources/abis/*.json\" --out-dir=\"./src/types/deth\""
|
||||
"typechain": "typechain --target \"ethers-v5\" --discriminate-types --glob \"./src/resources/abis/*.json\" --out-dir=\"./src/types/deth\"",
|
||||
"clean": "rm -rf --interactive=never cache/*"
|
||||
},
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
@ -74,6 +75,6 @@
|
||||
"tsc-alias": "^1.2.11",
|
||||
"tsconfig-paths": "^4.1.2",
|
||||
"typechain": "^8.1.1",
|
||||
"typescript": "^5.1.0-dev.20230310"
|
||||
"typescript": "^5"
|
||||
}
|
||||
}
|
||||
|
@ -3,4 +3,4 @@ export * as Data from "lib/data"
|
||||
export * as Network from "lib/chain"
|
||||
export * as Web from "lib/web"
|
||||
export * as Utils from "lib/utils"
|
||||
export * from "lib/main"
|
||||
export * from "lib/core"
|
@ -1,12 +1,7 @@
|
||||
// Tooling for interaction with the blockchain.
|
||||
|
||||
// Types
|
||||
import { MarkOptional } from 'ts-essentials'
|
||||
import * as Types from 'types/sdk/chain'
|
||||
|
||||
// External imports
|
||||
import { TransactionRequest } from '@ethersproject/abstract-provider'
|
||||
import { BaseContract, BigNumber, ContractTransaction, providers, Signer, VoidSigner } from 'ethers'
|
||||
import { randomBytes } from 'crypto'
|
||||
|
||||
// Our local types
|
||||
import {
|
||||
ERC20Tornado__factory,
|
||||
@ -21,19 +16,19 @@ import {
|
||||
} from 'types/deth'
|
||||
import { Multicall3 } from 'types/deth/Multicall3Contract'
|
||||
|
||||
// External imports
|
||||
import { TransactionRequest } from '@ethersproject/abstract-provider'
|
||||
import { BaseContract, BigNumber, ContractTransaction, providers, Signer, VoidSigner } from 'ethers'
|
||||
import { randomBytes } from 'crypto'
|
||||
|
||||
// Local modules
|
||||
import { OnchainData } from 'lib/data'
|
||||
import { ErrorUtils } from './utils'
|
||||
import { MarkOptional } from 'ts-essentials'
|
||||
import { ErrorUtils, HexUtils } from 'lib/utils'
|
||||
|
||||
// We use a vanilla provider here, but in reality we will probably
|
||||
// add a censorship-checking custom derivative of it
|
||||
type Provider = providers.Provider
|
||||
|
||||
export function prepareAddress(address: string): string {
|
||||
return (address.slice(0, 2) == '0x' ? address.slice(2) : address).toLowerCase().padStart(64, '0')
|
||||
}
|
||||
|
||||
/**
|
||||
* The Chain class stores Tornado-agnostic chain data and also
|
||||
* handles such interactions.
|
||||
@ -43,6 +38,7 @@ export class Chain {
|
||||
public provider: Provider
|
||||
private _emptySigner: VoidSigner
|
||||
public chainId?: number
|
||||
public symbol?: string
|
||||
|
||||
constructor(provider: Provider, signer?: Signer) {
|
||||
this.provider = provider
|
||||
@ -55,14 +51,27 @@ export class Chain {
|
||||
return this.chainId
|
||||
}
|
||||
|
||||
async latestBlockNum(): Promise<number> {
|
||||
async getChainSymbol(): Promise<string> {
|
||||
if (!this.symbol) this.symbol = await OnchainData.getNetworkSymbol(String(await this.getChainId()))
|
||||
return this.symbol
|
||||
}
|
||||
|
||||
latestBlockNum(): Promise<number> {
|
||||
return this.provider.getBlockNumber()
|
||||
}
|
||||
|
||||
async getAccountBalance(account: string): Promise<BigNumber> {
|
||||
getAccountBalance(account: string): Promise<BigNumber> {
|
||||
return this.provider.getBalance(account)
|
||||
}
|
||||
|
||||
getGasPrice(): Promise<BigNumber> {
|
||||
return this.provider.getGasPrice()
|
||||
}
|
||||
|
||||
getTokenContract(tokenAddress: string): ERC20 {
|
||||
return Contracts.getToken(tokenAddress, this.signer ?? this.provider)
|
||||
}
|
||||
|
||||
async getTokenDecimals(token: string): Promise<BigNumber> {
|
||||
let treq = {
|
||||
to: token,
|
||||
@ -74,16 +83,12 @@ export class Chain {
|
||||
async getTokenBalance(account: string, token: string, normalized: boolean = false): Promise<BigNumber> {
|
||||
let treq = {
|
||||
to: token,
|
||||
data: '0x70a08231000000000000000000000000' + prepareAddress(account)
|
||||
data: '0x70a08231000000000000000000000000' + HexUtils.prepareAddress(account)
|
||||
}
|
||||
let divisor = normalized ? BigNumber.from(10).pow(await this.getTokenDecimals(token)) : 1
|
||||
return BigNumber.from(await this._emptySigner.call(treq)).div(divisor)
|
||||
}
|
||||
|
||||
getTokenContract(tokenAddress: string): ERC20 {
|
||||
return ERC20__factory.connect(tokenAddress, this.provider)
|
||||
}
|
||||
|
||||
async populateBatchCall(
|
||||
callStruct: Array<MarkOptional<Multicall3.Call3ValueStruct, 'value'>>
|
||||
): Promise<TransactionRequest> {
|
||||
@ -181,7 +186,13 @@ export namespace Contracts {
|
||||
return contractMap.get(key) as TornadoInstance
|
||||
}
|
||||
|
||||
export async function getTornToken(signerOrProvider: Signer | Provider): Promise<ERC20> {
|
||||
export function getToken(tokenAddress: string, signerOrProvider: Signer | Provider): ERC20 {
|
||||
if (!contractMap.has(tokenAddress))
|
||||
contractMap.set(tokenAddress, _getContract<ERC20>('ERC20', tokenAddress, signerOrProvider))
|
||||
return contractMap.get(tokenAddress) as ERC20
|
||||
}
|
||||
|
||||
export function getTornToken(signerOrProvider: Signer | Provider): ERC20 {
|
||||
const key = '$TORN'
|
||||
if (!contractMap.has(key)) {
|
||||
contractMap.set(
|
||||
|
@ -1,37 +1,41 @@
|
||||
// ts-essentials
|
||||
import { DeepRequired } from 'ts-essentials'
|
||||
import { DeepRequired, MarkOptional, MarkRequired } from 'ts-essentials'
|
||||
|
||||
// Local types
|
||||
import { RelayerProperties } from 'types/sdk/data'
|
||||
import { Options, Transactions } from 'types/sdk/main'
|
||||
import { RelayerProperties as RelayerDataProperties } from 'types/sdk/data'
|
||||
import { Options, Transactions } from 'types/sdk/core'
|
||||
import { ZKDepositData, InputFor } from 'types/sdk/crypto'
|
||||
import { TornadoInstance, TornadoProxy } from 'types/deth'
|
||||
|
||||
// External imports
|
||||
import { BigNumber, EventFilter, providers } from 'ethers'
|
||||
import { parseUnits } from 'ethers/lib/utils'
|
||||
import { bigInt } from 'snarkjs'
|
||||
|
||||
// @ts-ignore
|
||||
import { parseIndexableString } from 'pouchdb-collate'
|
||||
|
||||
// Important local
|
||||
import { Docs, Cache, Types as DataTypes, Json, Constants } from 'lib/data'
|
||||
// Local imports
|
||||
import { Docs, Cache, Types as DataTypes, Json, Constants, OnchainData } from 'lib/data'
|
||||
import { Primitives } from 'lib/crypto'
|
||||
import { Contracts } from 'lib/chain'
|
||||
|
||||
// Other local imports
|
||||
import { OnchainData } from 'lib/data'
|
||||
import { ErrorUtils } from 'lib/utils'
|
||||
import { Chain } from 'lib/chain'
|
||||
import { parseUnits } from 'ethers/lib/utils'
|
||||
import { Contracts, Chain } from 'lib/chain'
|
||||
import { ErrorUtils, ObjectUtils } from 'lib/utils'
|
||||
|
||||
type Provider = providers.Provider
|
||||
|
||||
type BackupDepositDoc = {
|
||||
pathstring: string
|
||||
network: string
|
||||
denomination: string
|
||||
token: string
|
||||
invoice?: string
|
||||
note?: string
|
||||
}
|
||||
|
||||
type RelayerProperties = MarkOptional<
|
||||
Pick<RelayerDataProperties, 'address' | 'serviceFeePercent' | 'prices'>,
|
||||
'serviceFeePercent' | 'prices'
|
||||
>
|
||||
|
||||
export class Core {
|
||||
chain: Chain
|
||||
caches: Map<string, Cache.Base<Docs.Base>>
|
||||
@ -39,7 +43,7 @@ export class Core {
|
||||
|
||||
constructor(provider: providers.Provider) {
|
||||
this.chain = new Chain(provider)
|
||||
this.caches = new Map<string, Cache.Base<Docs.Base>>()
|
||||
this.caches = new Map<string, Cache.Syncable<Docs.Base>>()
|
||||
this.instances = new Map<string, TornadoInstance>()
|
||||
}
|
||||
|
||||
@ -65,7 +69,7 @@ export class Core {
|
||||
|
||||
async getProxy(): Promise<TornadoProxy> {
|
||||
const chainId = await this.chain.getChainId()
|
||||
return Contracts.getProxy(String(chainId), this.chain.signer ?? this.chain.provider)
|
||||
return Contracts.getProxy(String(chainId), this.chain.provider)
|
||||
}
|
||||
|
||||
async buildDepositProof(
|
||||
@ -74,7 +78,7 @@ export class Core {
|
||||
recipientAddress: string,
|
||||
zkDepositsData: ZKDepositData,
|
||||
options?: Options.Core.BuildDepositProof
|
||||
): Promise<any> {
|
||||
): Promise<Array<string>> {
|
||||
return (
|
||||
await this.buildDepositProofs(
|
||||
instance,
|
||||
@ -88,10 +92,10 @@ export class Core {
|
||||
|
||||
/**
|
||||
* @param instance This is the Tornado Instance which will be withdrawn from.
|
||||
* @param relayerProperties The properties of the relayer that is going to be used for the withdrawals. These properties are included in the ZK proof.
|
||||
* @param relayerProperties The properties of the relayer that is going to be used for the withdrawals. If the service fee is 0, it is assumed that there is no relayer, but that a manual wallet withdraw is being made. These properties are included in the ZK proof.
|
||||
* @param recipientAddresses The recipient addresses which should receive the withdrawals, in order.
|
||||
* @param zkDepositsData These represent the public and private values, reconstructed from the deposit note, generated during the building of deposit transactions, used for building the proof of knowledge statement for withdrawal, for each withdrawal (in this context).
|
||||
* @param options Additional options which allow the user to skip checking whether the notes are spent or changing the target merkle tree height.
|
||||
* @param options Numerous options which most importantly allow a user to specify whether he is buying ETH, whether to check proof data validity and finally to modulate the gas prices which will be used to calculate the gas fees paid to the relayer.
|
||||
* @returns The proofs for which the user should then decide whether to use a relayer (recommended, but decide carefully which one) or use his own wallet (if needed).
|
||||
*/
|
||||
async buildDepositProofs(
|
||||
@ -100,16 +104,19 @@ export class Core {
|
||||
recipientAddresses: Array<string>,
|
||||
zkDepositsData: Array<ZKDepositData>,
|
||||
options?: Options.Core.BuildDepositProof
|
||||
): Promise<Array<any>> {
|
||||
): Promise<Array<Array<string>>> {
|
||||
// Extract commitments and nullifier hashes
|
||||
const hexCommitments: string[] = []
|
||||
const hexNullifierHashes: string[] = []
|
||||
const purchaseAmounts = options?.ethPurchaseAmounts ?? new Array(zkDepositsData.length)
|
||||
|
||||
console.log('\nChecking inputs.\n')
|
||||
|
||||
if (zkDepositsData.length !== recipientAddresses.length)
|
||||
throw ErrorUtils.getError(
|
||||
'Core.buildDepositProofs: the number of recipients must equal the length of zkDepositsData.'
|
||||
)
|
||||
|
||||
if (zkDepositsData.length !== purchaseAmounts.length)
|
||||
throw ErrorUtils.getError(
|
||||
'Core.buildDepositProofs: if purchase amounts is specified, it must equal the length of zkDepositsData.'
|
||||
@ -120,20 +127,26 @@ export class Core {
|
||||
hexNullifierHashes.push(deposit.hexNullifierHash)
|
||||
})
|
||||
|
||||
console.log('\nGetting lookup keys.\n')
|
||||
|
||||
// Determine cache name
|
||||
const lookupKeys = await this.getInstanceLookupKeys(instance.address)
|
||||
const name = 'Deposit' + (lookupKeys.network + lookupKeys.token + lookupKeys.denomination).toUpperCase()
|
||||
const name = 'Deposits' + (lookupKeys.network + lookupKeys.token + lookupKeys.denomination).toUpperCase()
|
||||
|
||||
// Find all leaf indices by reading from cache
|
||||
const leafIndices = await this._findLeafIndices(name, hexCommitments)
|
||||
console.log('\nLeaves and indices.\n')
|
||||
|
||||
// Find all leaves & indices by reading from cache
|
||||
const [leaves, leafIndices] = await this._findLeavesAndIndices(name, hexCommitments)
|
||||
const invalidCommitments: string[] = []
|
||||
|
||||
// Determine whether we will be checking whether notes are spent
|
||||
const spentNotes: string[] = []
|
||||
const checkSpent = options?.checkNotesSpent !== false
|
||||
const spentNotes: string[] = []
|
||||
|
||||
console.log('\nNote checking.\n')
|
||||
|
||||
// If yes, immediately check it with the supplied Tornado Instance
|
||||
const checkSpentArray = checkSpent ? await instance.isSpentArray(hexNullifierHashes) : null
|
||||
const checkSpentArray = checkSpent ? await instance.isSpentArray(hexNullifierHashes) : undefined
|
||||
|
||||
// Check whether a commitment has not been found in all deposits, meaning that it is invalid
|
||||
// Also add the invalid commitments. We can do leafIndices[i] because the matched one are concatenated
|
||||
@ -148,37 +161,65 @@ export class Core {
|
||||
const commitmentsAreInvalid = invalidCommitments.length !== 0
|
||||
const notesAreSpent = spentNotes.length !== 0
|
||||
|
||||
console.log('\nErrors.\n')
|
||||
|
||||
if (commitmentsAreInvalid || notesAreSpent)
|
||||
throw ErrorUtils.getError(
|
||||
`Core.buildWithdrawalTxs: ` +
|
||||
`Core.buildDepositProofs: ` +
|
||||
(commitmentsAreInvalid
|
||||
? `following commitments are invalid:\n\n${invalidCommitments.join('\n')}\n\n`
|
||||
: '') +
|
||||
(notesAreSpent
|
||||
? `${commitmentsAreInvalid ? 'and ' : ''}following notes are already spent:\n\n${spentNotes.join(
|
||||
'\n'
|
||||
)}\n\n`
|
||||
? `${
|
||||
commitmentsAreInvalid ? 'and ' : ''
|
||||
}following notes are already spent or invalid:\n\n${spentNotes.join('\n')}\n\n`
|
||||
: '')
|
||||
)
|
||||
|
||||
// Otherwise, build the merkle tree from the leaf indices
|
||||
// We have to slice to get the leaf indices in order
|
||||
console.log('\nMerkle tree.\n')
|
||||
|
||||
// Otherwise, build the merkle tree from the leaves
|
||||
const merkleTree = Primitives.buildMerkleTree({
|
||||
height: options?.merkleTreeHeight ?? Constants.MERKLE_TREE_HEIGHT,
|
||||
leaves: leafIndices.slice(zkDepositsData.length).map((leafIndex) => String(leafIndex))
|
||||
leaves: leaves
|
||||
})
|
||||
|
||||
const root: string = merkleTree.root()
|
||||
const checkKnownRoot: boolean = options?.checkKnownRoot ?? true
|
||||
|
||||
// Check whether the root is valid
|
||||
if (!(await instance.isKnownRoot(root)))
|
||||
if (checkKnownRoot && !(await instance.isKnownRoot(root)))
|
||||
throw ErrorUtils.getError(
|
||||
'Core.buildWithdrawalTxs: the merkle tree created is not valid, something went wrong with syncing.'
|
||||
'Core.buildDepositProofs: the merkle tree created is not valid, something went wrong with syncing.'
|
||||
)
|
||||
|
||||
// Compute proofs
|
||||
const inputsForProofs: InputFor.ZKProof[] = []
|
||||
console.log('\nProof data invariant.\n')
|
||||
|
||||
// Rest of note invariant arguments
|
||||
const inputsForProofs: InputFor.ZKProof[] = []
|
||||
const gasPrice = options?.gasPrice ?? (await this.chain.getGasPrice())
|
||||
const gasPriceCushion = options?.gasPrice ?? gasPrice.mul(10).div(100)
|
||||
|
||||
// In reality, if a manual withdraw is made, we don't differentiate it from a relayer withdraw
|
||||
// Since it is only serviceFee 0 AND without a token price, the function will not buy more tokens
|
||||
const serviceFee = relayerProperties.serviceFeePercent ?? 0
|
||||
const tokenPrice = relayerProperties.prices?.get(lookupKeys.token)
|
||||
const decimals =
|
||||
// @ts-expect-error
|
||||
bigInt(10).pow(
|
||||
options?.tokenDecimals ?? (await OnchainData.getTokenDecimals(lookupKeys.network, lookupKeys.token))
|
||||
)
|
||||
const toWithdraw = BigNumber.from(lookupKeys.denomination).mul(decimals)
|
||||
|
||||
// TODO: Decide if necessary
|
||||
if (!tokenPrice && lookupKeys.token !== (await this.chain.getChainSymbol()))
|
||||
throw ErrorUtils.getError(
|
||||
'Core.buildDepositProofs: a token price MUST be supplied if the token withdrawn is not native.'
|
||||
)
|
||||
|
||||
console.log('\nConstruct.\n')
|
||||
|
||||
// Compute proofs
|
||||
for (let i = 0, len = zkDepositsData.length; i < len; i++) {
|
||||
inputsForProofs.push({
|
||||
public: {
|
||||
@ -188,8 +229,17 @@ export class Core {
|
||||
hexNullifierHash: zkDepositsData[i].hexNullifierHash,
|
||||
recipientAddress: recipientAddresses[i],
|
||||
relayerAddress: relayerProperties.address,
|
||||
fee: 5, // TODO: placeholder
|
||||
refund: purchaseAmounts[i] ?? 0
|
||||
fee: this._calcWithdrawalFee(
|
||||
toWithdraw,
|
||||
decimals,
|
||||
gasPrice,
|
||||
gasPriceCushion,
|
||||
serviceFee,
|
||||
purchaseAmounts[i],
|
||||
tokenPrice
|
||||
),
|
||||
// @ts-expect-error
|
||||
refund: bigInt(purchaseAmounts[i].toString()) ?? bigInt(0)
|
||||
},
|
||||
private: {
|
||||
nullifier: zkDepositsData[i].nullifier,
|
||||
@ -198,9 +248,68 @@ export class Core {
|
||||
})
|
||||
}
|
||||
|
||||
console.log('\nCalc and return.\n')
|
||||
|
||||
return await Primitives.calcDepositProofs(inputsForProofs)
|
||||
}
|
||||
|
||||
private _calcWithdrawalFee(
|
||||
toWithdraw: BigNumber,
|
||||
decimals: BigNumber,
|
||||
gasPrice: BigNumber,
|
||||
gasPriceCushion: BigNumber,
|
||||
relayerServiceFee: number,
|
||||
ethBought?: BigNumber,
|
||||
tokenPriceInEth?: BigNumber
|
||||
): typeof bigInt {
|
||||
const factor = BigNumber.from(10).pow(String(relayerServiceFee).length)
|
||||
const baseRelayerFee = toWithdraw.mul(BigNumber.from(relayerServiceFee).mul(factor)).div(factor)
|
||||
const txCost = gasPrice.add(gasPriceCushion).mul(5e5)
|
||||
if (ethBought && tokenPriceInEth) {
|
||||
// @ts-expect-error
|
||||
return bigInt(txCost.add(ethBought).mul(decimals).div(tokenPriceInEth).add(baseRelayerFee).toString())
|
||||
}
|
||||
// @ts-expect-error
|
||||
else return bigInt(txCost.add(baseRelayerFee).toString())
|
||||
}
|
||||
|
||||
async loadNotes(
|
||||
indexes?: Array<number>,
|
||||
keys?: Partial<DataTypes.Keys.InstanceLookup>
|
||||
): Promise<Array<ZKDepositData>> {
|
||||
const rows = await Cache.loadContents<Docs.Note>('DepositNotes')
|
||||
|
||||
let docs: Array<Docs.Note | undefined> = []
|
||||
let notes: Array<string> = []
|
||||
|
||||
if (indexes)
|
||||
for (let i = 0, len = rows.length; i < len; i++) {
|
||||
const id = parseIndexableString(rows[i].id)[0]
|
||||
if (id === indexes[i]) docs.push(rows[i].doc)
|
||||
}
|
||||
else docs = rows.map((row) => row.doc)
|
||||
|
||||
if (keys)
|
||||
docs.forEach((doc) => {
|
||||
const idNetworkMatches = doc && keys.network ? keys.network === doc?.network : true
|
||||
const andTokenSymbolMatches = idNetworkMatches && (keys.token ? keys.token === doc?.token : true)
|
||||
const lastlyDenominationMatches =
|
||||
andTokenSymbolMatches && (keys.denomination ? keys.denomination === doc?.denomination : true)
|
||||
if (lastlyDenominationMatches && doc?.note) notes.push(doc.note)
|
||||
})
|
||||
else notes = docs.filter((doc) => ObjectUtils.exists(doc?.note)).map((doc) => doc!.note)
|
||||
|
||||
return this.parseNotes(notes)
|
||||
}
|
||||
|
||||
parseNotes(notes: Array<string>): Array<ZKDepositData> {
|
||||
return notes.map((note) => Primitives.parseNote(note))
|
||||
}
|
||||
|
||||
parseNote(note: string): ZKDepositData {
|
||||
return this.parseNotes([note])[0]
|
||||
}
|
||||
|
||||
async createInvoice(
|
||||
instance: TornadoInstance,
|
||||
options?: Omit<Options.Core.Invoice, 'depositsPerInstance'>
|
||||
@ -261,9 +370,21 @@ export class Core {
|
||||
const deposit = Primitives.createDeposit()
|
||||
const note = Primitives.createNote(deposit.preimage)
|
||||
|
||||
if (backupNotes) notesToBackup.push({ pathstring: pathstring, note: note })
|
||||
if (backupNotes)
|
||||
notesToBackup.push({
|
||||
network: lookupKeys.network,
|
||||
denomination: lookupKeys.denomination,
|
||||
token: lookupKeys.token,
|
||||
note: note
|
||||
})
|
||||
|
||||
if (backupInvoices) invoicesToBackup.push({ pathstring: pathstring, invoice: deposit.hexCommitment })
|
||||
if (backupInvoices)
|
||||
invoicesToBackup.push({
|
||||
network: lookupKeys.network,
|
||||
denomination: lookupKeys.denomination,
|
||||
token: lookupKeys.token,
|
||||
invoice: deposit.hexCommitment
|
||||
})
|
||||
|
||||
if (!doNotPopulate) {
|
||||
txs.push({
|
||||
@ -305,8 +426,10 @@ export class Core {
|
||||
await cache.db
|
||||
.bulkDocs(
|
||||
backupData.map((entry) => {
|
||||
if (entry.note) return new Docs.Note(++id, entry.pathstring, entry.note)
|
||||
else if (entry.invoice) return new Docs.Invoice(++id, entry.pathstring, entry.invoice)
|
||||
if (entry.note)
|
||||
return new Docs.Note(++id, entry.network, entry.token, entry.denomination, entry.note)
|
||||
else if (entry.invoice)
|
||||
return new Docs.Invoice(++id, entry.network, entry.token, entry.denomination, entry.invoice)
|
||||
}) as Array<T>
|
||||
)
|
||||
.catch((err) => {
|
||||
@ -318,6 +441,13 @@ export class Core {
|
||||
})
|
||||
}
|
||||
|
||||
loadCache<T extends Docs.Base, C extends Cache.Base<T>>(cacheName: string): C {
|
||||
if (!this.caches.has(cacheName)) {
|
||||
this.caches.set(cacheName, new Cache.Base<T>(cacheName))
|
||||
}
|
||||
return this.caches.get(cacheName) as C
|
||||
}
|
||||
|
||||
async syncMultiple(instances: Array<TornadoInstance>, syncOptions?: Options.Core.Sync): Promise<void> {
|
||||
for (const instance of instances) {
|
||||
await this.sync(instance, syncOptions)
|
||||
@ -350,21 +480,41 @@ export class Core {
|
||||
}`,
|
||||
pathstring = name.substring(action.length).toLowerCase()
|
||||
|
||||
let cache: Cache.Syncable<Docs.Base>, toDoc: (_: any) => Docs.Base, filter: EventFilter
|
||||
let cache: Cache.Syncable<Docs.Base>,
|
||||
toDoc: (_: any) => Docs.Base,
|
||||
filter: EventFilter,
|
||||
numEntries: number
|
||||
|
||||
if (action == 'Deposit') {
|
||||
toDoc = (resp: any) => new Docs.Deposit(resp)
|
||||
cache = new Cache.Deposit(name, syncOptions.cache)
|
||||
cache = this.caches.has(name)
|
||||
? (this.caches.get(name)! as Cache.Deposit)
|
||||
: new Cache.Deposit(name, syncOptions.cache)
|
||||
filter = instance.filters.Deposit(null, null, null)
|
||||
} else {
|
||||
toDoc = (resp: any) => new Docs.Withdrawal(resp)
|
||||
cache = new Cache.Withdrawal(name, syncOptions.cache)
|
||||
cache = this.caches.has(name)
|
||||
? (this.caches.get(name)! as Cache.Withdrawal)
|
||||
: new Cache.Withdrawal(name, syncOptions.cache)
|
||||
filter = instance.filters.Withdrawal(null, null, null, null)
|
||||
}
|
||||
|
||||
// Assign pooler
|
||||
cache.sync.pooler = await cache.sync.initializePooler(cache.getCallbacks(instance))
|
||||
|
||||
// Decide whether we have a latest block
|
||||
numEntries = (await cache.db.info()).doc_count
|
||||
|
||||
// Check for synced blocks
|
||||
if (0 < numEntries) {
|
||||
const [lastSyncedBlock, ,] = parseIndexableString(
|
||||
(await cache.db.allDocs({ descending: true, limit: 1 })).rows[0].id
|
||||
)
|
||||
syncOptions.blocks.startBlock =
|
||||
lastSyncedBlock < syncOptions.blocks.startBlock ? syncOptions.blocks.startBlock : lastSyncedBlock
|
||||
syncOptions.blocks.blockDelta = this._getBlockDelta(syncOptions)
|
||||
}
|
||||
|
||||
// Start synchronizing
|
||||
let dbPromises = []
|
||||
|
||||
@ -373,14 +523,14 @@ export class Core {
|
||||
blockDelta = syncOptions.blocks.blockDelta,
|
||||
targetBlock = syncOptions.blocks.targetBlock,
|
||||
concurrencyLimit = syncOptions.cache.sync.concurrencyLimit;
|
||||
currentBlock < targetBlock + blockDelta;
|
||||
currentBlock < targetBlock;
|
||||
currentBlock += blockDelta
|
||||
) {
|
||||
if (cache.sync.pooler.pending < concurrencyLimit) {
|
||||
if (currentBlock < targetBlock) {
|
||||
await cache.sync.pooler.pool(currentBlock, currentBlock + blockDelta)
|
||||
const sum = currentBlock + blockDelta
|
||||
if (currentBlock + blockDelta < targetBlock) {
|
||||
await cache.sync.pooler.pool(currentBlock, sum)
|
||||
} else {
|
||||
let sum = currentBlock + blockDelta
|
||||
await cache.sync.pooler.pool(currentBlock, sum - (sum % targetBlock))
|
||||
}
|
||||
} else {
|
||||
@ -452,8 +602,7 @@ export class Core {
|
||||
|
||||
syncOptions.blocks.targetBlock = syncOptions.blocks.targetBlock ?? (await this.chain.latestBlockNum())
|
||||
|
||||
syncOptions.blocks.blockDelta =
|
||||
syncOptions.blocks.blockDelta ?? (syncOptions.blocks.targetBlock - syncOptions.blocks.startBlock) / 20
|
||||
syncOptions.blocks.blockDelta = this._getBlockDelta(syncOptions)
|
||||
|
||||
// cache
|
||||
// db
|
||||
@ -467,14 +616,24 @@ export class Core {
|
||||
return syncOptions as DeepRequired<Options.Core.Sync>
|
||||
}
|
||||
|
||||
private _getBlockDelta(syncOptions?: Options.Core.Sync): number {
|
||||
return Math.floor(
|
||||
syncOptions?.blocks?.blockDelta ??
|
||||
(syncOptions!.blocks!.targetBlock! - syncOptions!.blocks!.startBlock!) / 20
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* @param instanceName The name of the instance as created in `_sync` function.
|
||||
* @param commitments The commitments for which the leaf index values are to be noted down extra.
|
||||
* @returns The result of concatenating the array of leaf indices found by matching them with the provided commitment values, followed by the array of all leaf indices, including all of the formerly mentioned values given that they are valid. Values which have not been matched, meaning probably invalid values, will be `0`.
|
||||
*/
|
||||
private async _findLeafIndices(instanceName: string, commitments: Array<string>): Promise<Array<number>> {
|
||||
const matchedLeafIndices = new Array<number>(commitments.length).fill(0)
|
||||
const leafIndices: Array<number> = []
|
||||
private async _findLeavesAndIndices(
|
||||
instanceName: string,
|
||||
commitments: Array<string>
|
||||
): Promise<[Array<string>, Array<number>]> {
|
||||
const indices = new Array<number>(commitments.length).fill(0)
|
||||
const leaves: Array<string> = []
|
||||
|
||||
// Either load all deposit events from memory or from cache
|
||||
let cache: Cache.Base<Docs.Deposit>
|
||||
@ -493,24 +652,23 @@ export class Core {
|
||||
)
|
||||
}
|
||||
|
||||
// Otherwise start looking for commitment leaf indices and also pick up
|
||||
// all other leafs on the way
|
||||
// Otherwise start looking for commitment leaf indices and also pick up all other leafs on the way
|
||||
for (const row of docs.rows) {
|
||||
const [, leafIndex, loadedCommitment] = parseIndexableString(row.id)
|
||||
const index = commitments.findIndex((commitment) => commitment === loadedCommitment)
|
||||
|
||||
// If some commitment is found then add the leaf index and remove that commitment
|
||||
if (index !== -1) {
|
||||
matchedLeafIndices[index] = leafIndex
|
||||
indices[index] = leafIndex
|
||||
commitments.splice(index, 1)
|
||||
}
|
||||
|
||||
// In any case push every leaf
|
||||
leafIndices.push(leafIndex)
|
||||
leaves.push(BigNumber.from(loadedCommitment).toString())
|
||||
}
|
||||
|
||||
// Concat matched and all leaf indices
|
||||
return matchedLeafIndices.concat(leafIndices)
|
||||
return [leaves, indices]
|
||||
}
|
||||
|
||||
async getInstanceLookupKeys(instanceAddress: string): Promise<DataTypes.Keys.InstanceLookup> {
|
||||
@ -521,7 +679,6 @@ export class Core {
|
||||
|
||||
const pathstring: string = Object.entries(lookupObj).find((el) => el[1] === instanceAddress)![0]
|
||||
|
||||
// I like JS/TS
|
||||
const network = pathstring.match('[0-9]+')![0],
|
||||
token = pathstring.substring(network.length).match('[a-z]+')![0],
|
||||
denomination = pathstring.substring(network.length + token.length)
|
@ -50,7 +50,8 @@ export namespace Primitives {
|
||||
}
|
||||
|
||||
export function parseNote(hexNote: string): Types.ZKDepositData {
|
||||
const buffer = Buffer.from(hexNote, 'hex')
|
||||
const _hexNote = hexNote.split('_')[1] ?? hexNote
|
||||
const buffer = Buffer.from(_hexNote, 'hex')
|
||||
return createDeposit({
|
||||
// @ts-expect-error
|
||||
nullifier: bigInt.leBuff2int(buffer.subarray(0, 31)),
|
||||
@ -66,11 +67,11 @@ export namespace Primitives {
|
||||
secret: NumberUtils.randomBigInteger(31)
|
||||
}
|
||||
// @ts-expect-error
|
||||
let preimage = Buffer.concat([depositData.nullifier.leInt2Buff(31), depositData.secret.leInt2Buff(31)])
|
||||
let preimage = Buffer.concat([input.nullifier.leInt2Buff(31), input.secret.leInt2Buff(31)])
|
||||
let commitment = calcPedersenHash({ msg: preimage })
|
||||
let commitmentHex = HexUtils.bigIntToHex(commitment)
|
||||
// @ts-expect-error
|
||||
let nullifierHash = calcPedersenHash({ msg: depositData.nullifier.leInt2Buff(31) })
|
||||
let nullifierHash = calcPedersenHash({ msg: input.nullifier.leInt2Buff(31) })
|
||||
let nullifierHex = HexUtils.bigIntToHex(nullifierHash)
|
||||
return {
|
||||
nullifier: input.nullifier!,
|
||||
@ -87,10 +88,10 @@ export namespace Primitives {
|
||||
return new MerkleTree(inputs.height, inputs.leaves)
|
||||
}
|
||||
|
||||
export async function calcDepositProofs(inputs: Array<Types.InputFor.ZKProof>): Promise<Array<any>> {
|
||||
export async function calcDepositProofs(
|
||||
inputs: Array<Types.InputFor.ZKProof>
|
||||
): Promise<Array<Array<string>>> {
|
||||
const proofs: string[][] = []
|
||||
const args: any[][] = []
|
||||
|
||||
const groth16 = await Setup.getGroth16()
|
||||
const circuit = await Setup.getTornadoCircuit()
|
||||
const provingKey = await Setup.getProvingKey()
|
||||
@ -101,7 +102,6 @@ export namespace Primitives {
|
||||
// Compute Merkle Proof
|
||||
const { pathElements, pathIndex } = input.public.tree.path(input.public.leafIndex)
|
||||
|
||||
args.push([])
|
||||
proofs.push([])
|
||||
|
||||
const proofData = await genWitnessAndProve(
|
||||
@ -109,16 +109,16 @@ export namespace Primitives {
|
||||
{
|
||||
// Public inputs
|
||||
root: input.public.root,
|
||||
// @ts-ignore
|
||||
// @ts-expect-error
|
||||
nullifierHash: bigInt(input.public.hexNullifierHash),
|
||||
// @ts-ignore
|
||||
fee: bigInt(input.public.fee),
|
||||
// @ts-ignore
|
||||
refund: bigInt(input.public.refund),
|
||||
// @ts-ignore
|
||||
relayer: bigInt(input.public.relayerAddress),
|
||||
// @ts-ignore
|
||||
// @ts-expect-error
|
||||
recipient: bigInt(input.public.recipientAddress),
|
||||
// @ts-expect-error
|
||||
relayer: bigInt(input.public.relayerAddress),
|
||||
// @ts-expect-error
|
||||
fee: bigInt(input.public.fee),
|
||||
//
|
||||
refund: input.public.refund,
|
||||
|
||||
// Private inputs
|
||||
nullifier: input.private.nullifier,
|
||||
@ -132,21 +132,20 @@ export namespace Primitives {
|
||||
|
||||
proofs[i].push(toSolidityInput(proofData).proof)
|
||||
|
||||
args[i].push([
|
||||
proofs[i].push(
|
||||
input.public.root,
|
||||
input.public.hexNullifierHash,
|
||||
HexUtils.prepareAddress(input.public.recipientAddress, 20),
|
||||
// @ts-ignore
|
||||
HexUtils.prepareAddress(input.public.relayerAddress, 20),
|
||||
HexUtils.numberToHex(input.public.fee),
|
||||
HexUtils.numberToHex(input.public.refund)
|
||||
])
|
||||
'0x' + HexUtils.prepareAddress(input.public.recipientAddress, 20),
|
||||
'0x' + HexUtils.prepareAddress(input.public.relayerAddress, 20),
|
||||
HexUtils.bigIntToHex(input.public.fee),
|
||||
HexUtils.bigIntToHex(input.public.refund)
|
||||
)
|
||||
}
|
||||
|
||||
// Done. 🤷♀️
|
||||
groth16.terminate()
|
||||
|
||||
return proofs.concat(args)
|
||||
return proofs
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,11 +2,7 @@
|
||||
import { TornadoInstance } from 'types/deth'
|
||||
import * as Types from 'types/sdk/data'
|
||||
import { RelayerProperties } from 'types/sdk/data'
|
||||
import { Options } from 'types/sdk/main'
|
||||
|
||||
// Local logic
|
||||
import { NumberUtils, ErrorUtils } from 'lib/utils'
|
||||
import { AsyncUtils } from 'lib/utils'
|
||||
import { Options } from 'types/sdk/core'
|
||||
|
||||
// Big modules
|
||||
import { BigNumber } from 'ethers'
|
||||
@ -14,13 +10,15 @@ import { existsSync, mkdirSync } from 'fs'
|
||||
import { opendir, readFile, rm } from 'fs/promises'
|
||||
import { createInterface } from 'readline'
|
||||
|
||||
// Local logic
|
||||
import { AsyncUtils, NumberUtils, ErrorUtils } from 'lib/utils'
|
||||
|
||||
// PouchDB
|
||||
import PouchDB from 'pouchdb'
|
||||
import * as PouchDBAdapterMemory from 'pouchdb-adapter-memory'
|
||||
|
||||
// @ts-ignore
|
||||
import { toIndexableString } from 'pouchdb-collate'
|
||||
import { timeStamp } from 'console'
|
||||
|
||||
// Register plugins
|
||||
PouchDB.plugin(PouchDBAdapterMemory)
|
||||
@ -146,20 +144,24 @@ export namespace OnchainData {
|
||||
export async function getInstanceAttrSet<T>(
|
||||
key: string,
|
||||
paths: Array<{
|
||||
network: string
|
||||
token: string
|
||||
denomination: string
|
||||
network?: string
|
||||
token?: string
|
||||
denomination?: string
|
||||
}>
|
||||
): Promise<Array<T>> {
|
||||
const obj = await Json.load('onchain/quickLookup.json')
|
||||
return await Promise.all(
|
||||
paths.map((path) => Json.getValue(obj, [key, `${path.network}${path.token}${path.denomination}`]))
|
||||
paths.map((path) =>
|
||||
Json.getValue(obj, [key, `${path.network ?? '\0'}${path.token ?? '\0'}${path.denomination ?? '\0'}`])
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
// TODO: Add field key for classic or nova
|
||||
export async function getNetworkSymbol(networkId: string): Promise<string> {
|
||||
return (await getInstanceAttrSet<string>('networkSymbols', [{ network: networkId }]))[0]
|
||||
}
|
||||
|
||||
export async function getInstanceAddresses(
|
||||
export function getInstanceAddresses(
|
||||
paths: Array<{
|
||||
network: string
|
||||
token: string
|
||||
@ -177,7 +179,7 @@ export namespace OnchainData {
|
||||
return (await getInstanceAddresses([{ network: network, token: token, denomination: denomination }]))[0]
|
||||
}
|
||||
|
||||
export async function getInstanceDeployBlockNums(
|
||||
export function getInstanceDeployBlockNums(
|
||||
paths: Array<{
|
||||
network: string
|
||||
token: string
|
||||
@ -217,6 +219,10 @@ export namespace OnchainData {
|
||||
address: data['address']
|
||||
}
|
||||
}
|
||||
|
||||
export async function getTokenDecimals(network: string, token: string): Promise<number> {
|
||||
return (await getTokenData(network, token)).decimals
|
||||
}
|
||||
}
|
||||
|
||||
export namespace OffchainData {
|
||||
@ -307,23 +313,31 @@ export namespace Docs {
|
||||
}
|
||||
|
||||
export class Note extends Base {
|
||||
pathstring: string
|
||||
network: string
|
||||
token: string
|
||||
denomination: string
|
||||
note: string
|
||||
|
||||
constructor(index: number, pathstring: string, note: string) {
|
||||
super(toIndexableString([index, pathstring]))
|
||||
this.pathstring = pathstring
|
||||
constructor(index: number, network: string, token: string, denomination: string, note: string) {
|
||||
super(toIndexableString([index, network, denomination, token]))
|
||||
this.network = network
|
||||
this.token = token
|
||||
this.denomination = denomination
|
||||
this.note = note
|
||||
}
|
||||
}
|
||||
|
||||
export class Invoice extends Base {
|
||||
pathstring: string
|
||||
network: string
|
||||
token: string
|
||||
denomination: string
|
||||
invoice: string
|
||||
|
||||
constructor(index: number, pathstring: string, invoice: string) {
|
||||
super(toIndexableString([index, pathstring]))
|
||||
this.pathstring = pathstring
|
||||
constructor(index: number, network: string, token: string, denomination: string, invoice: string) {
|
||||
super(toIndexableString([index, network, denomination, token]))
|
||||
this.network = network
|
||||
this.token = token
|
||||
this.denomination = denomination
|
||||
this.invoice = invoice
|
||||
}
|
||||
}
|
||||
@ -335,6 +349,7 @@ export namespace Docs {
|
||||
miningFeePercent: number
|
||||
status: string
|
||||
chainId: number
|
||||
prices: Map<string, BigNumber>
|
||||
|
||||
constructor(url: string, properties: RelayerProperties) {
|
||||
super(toIndexableString([url]))
|
||||
@ -344,6 +359,7 @@ export namespace Docs {
|
||||
this.miningFeePercent = properties.miningFeePercent
|
||||
this.status = properties.status
|
||||
this.chainId = properties.chainId
|
||||
this.prices = properties.prices
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -354,10 +370,10 @@ export namespace Cache {
|
||||
|
||||
constructor(name: string, options?: Options.Cache.Database) {
|
||||
if (options?.persistent === false && options?.adapter !== 'memory' && options?.adapter !== null)
|
||||
throw ErrorUtils.getError('if not persistent, cache must use memory adapter.')
|
||||
throw ErrorUtils.getError('Cache.new: if not persistent, cache must use memory adapter.')
|
||||
|
||||
if (options?.adapter === 'memory' && options?.persistent === true)
|
||||
throw ErrorUtils.getError("can't specify memory adapter if persistent.")
|
||||
throw ErrorUtils.getError("Cache.new: can't specify memory adapter if persistent.")
|
||||
|
||||
const dbAdapter = options?.adapter ?? (options?.persistent === false ? 'memory' : 'leveldb')
|
||||
|
||||
@ -392,13 +408,13 @@ export namespace Cache {
|
||||
|
||||
async close(): Promise<void> {
|
||||
if (this.sync.pooler!.pending)
|
||||
throw ErrorUtils.getError("can't clear while pooler still has pending promises.")
|
||||
throw ErrorUtils.getError("Syncable.close: can't clear while pooler still has pending promises.")
|
||||
await super.close()
|
||||
}
|
||||
|
||||
async clear(): Promise<void> {
|
||||
if (this.sync.pooler!.pending)
|
||||
throw ErrorUtils.getError("can't clear while pooler still has pending promises.")
|
||||
throw ErrorUtils.getError("Syncable.clear: can't clear while pooler still has pending promises.")
|
||||
await super.clear()
|
||||
}
|
||||
}
|
||||
@ -440,13 +456,16 @@ export namespace Cache {
|
||||
`Core.loadCacheContents: there is no cache entry for ${nameOfContent}`
|
||||
)
|
||||
): Promise<DocsArray<T>> {
|
||||
const cache = new Cache.Base<T>(Files.getCachePath(nameOfContent))
|
||||
const cache = new Cache.Base<T>(nameOfContent)
|
||||
|
||||
const docs = await cache.db.allDocs({ include_docs: full }).catch((err) => {
|
||||
throw ErrorUtils.ensureError(err)
|
||||
})
|
||||
|
||||
if (docs.total_rows === 0) throw emptyError
|
||||
if (docs.total_rows === 0) {
|
||||
await cache.clear()
|
||||
throw emptyError
|
||||
}
|
||||
|
||||
return docs.rows as DocsArray<T>
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Local types
|
||||
import * as Crypto from 'types/sdk/crypto'
|
||||
import { Options } from 'types/sdk/main'
|
||||
import { Options } from 'types/sdk/core'
|
||||
|
||||
// Needed
|
||||
import { BigNumber } from 'ethers'
|
||||
@ -8,8 +8,8 @@ import { bigInt } from 'snarkjs'
|
||||
import { randomBytes } from 'crypto'
|
||||
|
||||
export namespace ErrorUtils {
|
||||
export function ensureError(value: unknown): Error {
|
||||
if (value instanceof Error) return value
|
||||
export function ensureError<T extends Error>(value: unknown): T {
|
||||
if (value instanceof Error) return value as T
|
||||
|
||||
let stringified = '[Unable to stringify the thrown value]'
|
||||
try {
|
||||
@ -17,7 +17,7 @@ export namespace ErrorUtils {
|
||||
} catch {}
|
||||
|
||||
const error = getError(`This value was thrown as is, not through an Error: ${stringified}`)
|
||||
return error
|
||||
return error as T
|
||||
}
|
||||
|
||||
export function getError(message: string): Error {
|
||||
@ -177,13 +177,9 @@ export namespace NumberUtils {
|
||||
isInteger: number = 1
|
||||
): number {
|
||||
isInteger = 0 < isInteger ? 1 : 0
|
||||
return (
|
||||
isInteger
|
||||
? Math.floor
|
||||
: (x: number) => {
|
||||
return x
|
||||
}
|
||||
)(Math.random() * (upperInclusive + isInteger - lowerInclusive) + lowerInclusive)
|
||||
return (isInteger ? Math.floor : (x: number) => x)(
|
||||
Math.random() * (upperInclusive + isInteger - lowerInclusive) + lowerInclusive
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -240,4 +236,8 @@ export namespace ObjectUtils {
|
||||
right: left
|
||||
}
|
||||
}
|
||||
|
||||
export function exists(obj: any): boolean {
|
||||
return obj !== undefined && obj !== null
|
||||
}
|
||||
}
|
||||
|
115
src/lib/web.ts
115
src/lib/web.ts
@ -1,34 +1,46 @@
|
||||
import axios from 'axios'
|
||||
|
||||
import { AxiosInstance } from 'axios'
|
||||
import { SocksProxyAgent } from 'socks-proxy-agent'
|
||||
import { Web3Provider, Networkish } from '@ethersproject/providers'
|
||||
import { RelayerOptions } from 'types/sdk/web'
|
||||
import { BigNumber } from 'ethers'
|
||||
import { ErrorUtils } from './utils'
|
||||
import { Cache, Docs } from './data'
|
||||
// Types
|
||||
import { Relayer as Types, RelayerOptions } from 'types/sdk/web'
|
||||
import { RelayerProperties } from 'types/sdk/data'
|
||||
|
||||
// HTTP and proxy
|
||||
import axios from 'axios'
|
||||
import { AxiosInstance, AxiosError, AxiosResponse } from 'axios'
|
||||
import { SocksProxyAgent } from 'socks-proxy-agent'
|
||||
|
||||
// Ethers
|
||||
import { BigNumber } from 'ethers'
|
||||
import { Web3Provider, Networkish } from '@ethersproject/providers'
|
||||
|
||||
// Local
|
||||
import { ErrorUtils } from 'lib/utils'
|
||||
import { Cache, Docs } from 'lib/data'
|
||||
|
||||
// It seems that the default HttpProvider offered by the normal web3 package
|
||||
// has some logic which either ignores the SocksProxyAgent or which falls back to
|
||||
// using no proxy for some reason. In any case, the Tornado-modified one, originally
|
||||
// modified by the Tornado Team or who else, seems to properly error out when Tor
|
||||
// is not running.
|
||||
// modified by the Tornado Team or whoever else conributed, seems to properly error
|
||||
// out when Tor is not running.
|
||||
const HttpProvider = require('web3-providers-http')
|
||||
|
||||
export interface TorOptions {
|
||||
export interface ObfuscationOptions {
|
||||
port?: number
|
||||
headers?: { name: string; value: string }[]
|
||||
rv?: string
|
||||
}
|
||||
|
||||
/**
|
||||
* You can also set up a SOCKS5 I2P tunnel on some port and then use that instead. Meaning that this should be compatible with I2P.
|
||||
*/
|
||||
export class TorProvider extends Web3Provider {
|
||||
constructor(url: string, torOpts: TorOptions, network?: Networkish) {
|
||||
constructor(url: string, torOpts?: ObfuscationOptions, network?: Networkish) {
|
||||
torOpts = torOpts ?? {}
|
||||
torOpts.rv = torOpts.rv ?? '102.0'
|
||||
const torPort = torOpts.port ?? 9050,
|
||||
headers = torOpts.headers ?? [
|
||||
{ name: 'User-Agent', value: 'Mozilla/5.0 (Windows NT 10.0; rv:102.0) Gecko/20100101 Firefox/102.0' }
|
||||
{
|
||||
name: 'User-Agent',
|
||||
value: `Mozilla/5.0 (Windows NT 10.0; rv:${torOpts.rv}) Gecko/20100101 Firefox/${torOpts.rv}`
|
||||
}
|
||||
]
|
||||
|
||||
super(
|
||||
@ -79,8 +91,9 @@ export class Relayer {
|
||||
private _miningFee?: number
|
||||
private _status?: string
|
||||
private _chainId?: number
|
||||
private _prices?: Map<string, BigNumber>
|
||||
|
||||
constructor(options: RelayerOptions, properties?: RelayerProperties) {
|
||||
constructor(options: Types.Options, properties?: RelayerProperties) {
|
||||
this.url = options.url
|
||||
this.httpClient = options.httpClient
|
||||
this._fetched = false
|
||||
@ -92,6 +105,7 @@ export class Relayer {
|
||||
this._serviceFee = properties.serviceFeePercent
|
||||
this._miningFee = properties.miningFeePercent
|
||||
this._status = properties.status
|
||||
this._prices = properties.prices
|
||||
this._fetched = true
|
||||
}
|
||||
}
|
||||
@ -121,6 +135,10 @@ export class Relayer {
|
||||
this._serviceFee = properties['tornadoServiceFee']
|
||||
this._miningFee = properties['miningFee']
|
||||
this._status = properties['health']['status']
|
||||
this._prices = Object.entries(properties['ethPrices']).reduce(
|
||||
(map, entry) => map.set(entry[0], BigNumber.from(entry[1])),
|
||||
new Map<string, BigNumber>()
|
||||
)
|
||||
this._fetched = true
|
||||
|
||||
return {
|
||||
@ -129,7 +147,8 @@ export class Relayer {
|
||||
chainId: this._chainId!,
|
||||
serviceFeePercent: this._serviceFee!,
|
||||
miningFeePercent: this._miningFee!,
|
||||
status: this._status!
|
||||
status: this._status!,
|
||||
prices: this._prices!
|
||||
}
|
||||
}
|
||||
|
||||
@ -166,6 +185,10 @@ export class Relayer {
|
||||
this._propertiesFetched('chainId')
|
||||
return this._chainId!
|
||||
}
|
||||
get prices(): Map<string, BigNumber> {
|
||||
this._propertiesFetched('prices')
|
||||
return this._prices!
|
||||
}
|
||||
|
||||
async getETHPurchasePrice(token: string): Promise<BigNumber> {
|
||||
return BigNumber.from(
|
||||
@ -178,13 +201,60 @@ export class Relayer {
|
||||
)
|
||||
}
|
||||
|
||||
// TODO: Relaying stuff and related
|
||||
async handleWithdrawal(
|
||||
instanceAddress: string,
|
||||
proof: Array<string>
|
||||
): Promise<Types.WithdrawalRequestResult> {
|
||||
const response = (await this.httpClient
|
||||
.post(this.url + '/v1/tornadoWithdraw', {
|
||||
contract: instanceAddress,
|
||||
proof: proof[0],
|
||||
args: proof.slice(1)
|
||||
})
|
||||
.catch(this._handleHTTPError)) as AxiosResponse
|
||||
|
||||
async relay(): Promise<any> {}
|
||||
const { id } = response.data
|
||||
|
||||
async calcWithdrawalFee(token: string, denomination: number): Promise<BigNumber> {
|
||||
//placeholder
|
||||
return BigNumber.from(0)
|
||||
let result: Types.WithdrawalRequestResult = { success: false },
|
||||
finished = false
|
||||
|
||||
while (!finished) {
|
||||
const statusResponse = (await this.httpClient
|
||||
.get(this.url + '/v1/jobs/' + id)
|
||||
.catch((err) => this._handleHTTPError(err, false))) as AxiosResponse
|
||||
|
||||
if (statusResponse.status === 200) {
|
||||
const { txHash, status, _, failedReason } = statusResponse.data
|
||||
|
||||
if (status === 'FAILED') {
|
||||
console.error(`\nRelayer.handleWithdrawal: withdrawal failed with reason: ${failedReason}\n`)
|
||||
finished = true
|
||||
}
|
||||
|
||||
if (status == 'CONFIRMED') {
|
||||
result.success = true
|
||||
result.txHash = txHash
|
||||
finished = true
|
||||
}
|
||||
}
|
||||
|
||||
await new Promise((resolve) => setTimeout(resolve, 3000))
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
private _handleHTTPError(err: AxiosError, httpThrow: boolean = true): void {
|
||||
err = ErrorUtils.ensureError(err)
|
||||
if (err.response) {
|
||||
if (httpThrow)
|
||||
// @ts-expect-error
|
||||
throw ErrorUtils.ensureError(err.response.data.error)
|
||||
// @ts-expect-error
|
||||
else console.error(err.response.data.error)
|
||||
} else if (err.request) {
|
||||
if (httpThrow) throw ErrorUtils.ensureError(err.request)
|
||||
else console.error(err.request)
|
||||
} else throw err
|
||||
}
|
||||
|
||||
// Cache
|
||||
@ -217,7 +287,8 @@ export class Relayer {
|
||||
chainId: this._chainId!,
|
||||
serviceFeePercent: this._serviceFee!,
|
||||
miningFeePercent: this._miningFee!,
|
||||
status: this._status!
|
||||
status: this._status!,
|
||||
prices: this._prices!
|
||||
})
|
||||
|
||||
await cache.db.put(doc).catch((err) => {
|
||||
|
@ -14,16 +14,16 @@
|
||||
"1cdai5000000": "0xD21be7248e0197Ee08E0c20D4a96DEBdaC3D20Af",
|
||||
"1usdc100": "0xd96f2B1c14Db8458374d9Aca76E26c3D18364307",
|
||||
"1usdc1000": "0x4736dCf1b7A3d580672CcE6E7c65cd5cc9cFBa9D",
|
||||
"1usdc10000": "",
|
||||
"1usdc100000": "",
|
||||
"1usdc10000": null,
|
||||
"1usdc100000": null,
|
||||
"1usdt100": "0x169AD27A470D064DEDE56a2D3ff727986b15D52B",
|
||||
"1usdt1000": "0x0836222F2B2B24A3F36f98668Ed8F0B38D1a872f",
|
||||
"1usdt10000": "",
|
||||
"1usdt100000": "",
|
||||
"1usdt10000": null,
|
||||
"1usdt100000": null,
|
||||
"1wbtc0.1": "0x178169B423a011fff22B9e3F3abeA13414dDD0F1",
|
||||
"1wbtc1": "0x610B717796ad172B316836AC95a2ffad065CeaB4",
|
||||
"1wbtc10": "0xbB93e510BbCD0B7beb5A853875f9eC60275CF498",
|
||||
"1wbtc100": "",
|
||||
"1wbtc100": null,
|
||||
"5eth0.1": "0x6Bf694a291DF3FeC1f7e69701E3ab6c592435Ae7",
|
||||
"5eth1": "0x3aac1cC67c2ec5Db4eA850957b967Ba153aD6279",
|
||||
"5eth10": "0x723B78e67497E85279CB204544566F4dC5d2acA0",
|
||||
@ -38,16 +38,32 @@
|
||||
"5cdai5000000": "0x57b2B8c82F065de8Ef5573f9730fC1449B403C9f",
|
||||
"5usdc100": "0x05E0b5B40B7b66098C2161A5EE11C5740A3A7C45",
|
||||
"5usdc1000": "0x23173fE8b96A4Ad8d2E17fB83EA5dcccdCa1Ae52",
|
||||
"5usdc10000": "",
|
||||
"5usdc100000": "",
|
||||
"5usdc10000": null,
|
||||
"5usdc100000": null,
|
||||
"5usdt100": "0x538Ab61E8A9fc1b2f93b3dd9011d662d89bE6FE6",
|
||||
"5usdt1000": "0x94Be88213a387E992Dd87DE56950a9aef34b9448",
|
||||
"5usdt10000": "",
|
||||
"5usdt100000": "",
|
||||
"5usdt10000": null,
|
||||
"5usdt100000": null,
|
||||
"5wbtc0.1": "0x242654336ca2205714071898f67E254EB49ACdCe",
|
||||
"5wbtc1": "0x776198CCF446DFa168347089d7338879273172cF",
|
||||
"5wbtc10": "0xeDC5d01286f99A066559F60a585406f3878a033e",
|
||||
"5wbtc100": ""
|
||||
"5wbtc100": null,
|
||||
"56bnb0.1": "0x84443CFd09A48AF6eF360C6976C5392aC5023a1F",
|
||||
"56bnb1": "0xd47438C816c9E7f2E2888E060936a499Af9582b3",
|
||||
"56bnb10": "0x330bdFADE01eE9bF63C209Ee33102DD334618e0a",
|
||||
"56bnb100": "0x1E34A77868E19A6647b1f2F47B51ed72dEDE95DD",
|
||||
"100xdai100": "0x1E34A77868E19A6647b1f2F47B51ed72dEDE95DD",
|
||||
"100xdai1000": "0xdf231d99Ff8b6c6CBF4E9B9a945CBAcEF9339178",
|
||||
"100xdai10000": "0xaf4c0B70B2Ea9FB7487C7CbB37aDa259579fe040",
|
||||
"100xdai100000": "0xa5C2254e4253490C54cef0a4347fddb8f75A4998",
|
||||
"137matic100": "0x1E34A77868E19A6647b1f2F47B51ed72dEDE95DD",
|
||||
"137matic1000": "0xdf231d99Ff8b6c6CBF4E9B9a945CBAcEF9339178",
|
||||
"137matic10000": "0xaf4c0B70B2Ea9FB7487C7CbB37aDa259579fe040",
|
||||
"137matic100000": "0xa5C2254e4253490C54cef0a4347fddb8f75A4998",
|
||||
"42161eth0.1": "0x84443CFd09A48AF6eF360C6976C5392aC5023a1F",
|
||||
"42161eth1": "0xd47438C816c9E7f2E2888E060936a499Af9582b3",
|
||||
"42161eth10": "0x330bdFADE01eE9bF63C209Ee33102DD334618e0a",
|
||||
"42161eth100": "0x1E34A77868E19A6647b1f2F47B51ed72dEDE95DD"
|
||||
},
|
||||
"deployedBlockNumber": {
|
||||
"1eth0.1": 9116966,
|
||||
@ -64,15 +80,63 @@
|
||||
"1cdai5000000": 12066053,
|
||||
"1usdc100": 9161958,
|
||||
"1usdc1000": 9161965,
|
||||
"1usdc10000": "",
|
||||
"1usdc100000": "",
|
||||
"1usdc10000": null,
|
||||
"1usdc100000": null,
|
||||
"1usdt100": 9162005,
|
||||
"1usdt1000": 9162012,
|
||||
"1usdt10000": "",
|
||||
"1usdt100000": "",
|
||||
"1usdt10000": null,
|
||||
"1usdt100000": null,
|
||||
"1wbtc0.1": 12067529,
|
||||
"1wbtc1": 12066652,
|
||||
"1wbtc10": 12067591,
|
||||
"1wbtc100": ""
|
||||
"1wbtc100": null,
|
||||
"5eth0.1": 3782581,
|
||||
"5eth1": 3782590,
|
||||
"5eth10": 3782593,
|
||||
"5eth100": 3782596,
|
||||
"5dai100": 4339088,
|
||||
"5dai1000": 4367659,
|
||||
"5dai10000": 4441492,
|
||||
"5dai100000": 4441488,
|
||||
"5cdai5000": 4441443,
|
||||
"5cdai50000": 4441489,
|
||||
"5cdai500000": 4441493,
|
||||
"5cdai5000000": 4441489,
|
||||
"5usdc100": 4441426,
|
||||
"5usdc1000": 4441492,
|
||||
"5usdc10000": null,
|
||||
"5usdc100000": null,
|
||||
"5usdt100": 4441490,
|
||||
"5usdt1000": 4441492,
|
||||
"5usdt10000": null,
|
||||
"5usdt100000": null,
|
||||
"5wbtc0.1": 4441488,
|
||||
"5wbtc1": 4441490,
|
||||
"5wbtc10": 4441490,
|
||||
"5wbtc100": null,
|
||||
"56bnb0.1": 8159279,
|
||||
"56bnb1": 8159286,
|
||||
"56bnb10": 8159290,
|
||||
"56bnb100": 8159296,
|
||||
"100xdai100": 17754566,
|
||||
"100xdai1000": 17754568,
|
||||
"100xdai10000": 17754572,
|
||||
"100xdai100000": 17754574,
|
||||
"137matic100": 16258013,
|
||||
"137matic1000": 16258032,
|
||||
"137matic10000": 16258046,
|
||||
"137matic100000": 16258053,
|
||||
"42161eth0.1": 3300000,
|
||||
"42161eth1": 3300000,
|
||||
"42161eth10": 3300000,
|
||||
"42161eth100": 3300000
|
||||
},
|
||||
"networkSymbols": {
|
||||
"1": "eth",
|
||||
"5": "eth",
|
||||
"56": "bnb",
|
||||
"100": "xdai",
|
||||
"137": "matic",
|
||||
"42161": "eth"
|
||||
}
|
||||
}
|
@ -5,19 +5,26 @@ import { solidity } from 'ethereum-waffle'
|
||||
import { providers } from 'ethers'
|
||||
import { parseUnits } from 'ethers/lib/utils'
|
||||
|
||||
import { ERC20 } from 'types/deth'
|
||||
import { ERC20, TornadoInstance } from 'types/deth'
|
||||
import { Json } from 'types/sdk/data'
|
||||
import { Core } from 'lib/main'
|
||||
import { Core } from 'lib/core'
|
||||
import { Chain, Contracts } from 'lib/chain'
|
||||
import { Files, OnchainData } from 'lib/data'
|
||||
import { Docs, Files, OnchainData, Cache } from 'lib/data'
|
||||
import { ErrorUtils } from 'lib/utils'
|
||||
import { TorProvider } from 'lib/web'
|
||||
|
||||
// Data
|
||||
// @ts-expect-error
|
||||
import { parseIndexableString } from 'pouchdb-collate'
|
||||
import compareDeposits from './resources/deposits_eth_0.1.json'
|
||||
import { Primitives } from 'lib/crypto'
|
||||
import { ZKDepositData } from 'types/sdk/crypto'
|
||||
|
||||
chai.use(solidity)
|
||||
|
||||
const expect = chai.expect
|
||||
|
||||
describe('main', () => {
|
||||
describe.only('main', () => {
|
||||
const torify = process.env.TORIFY === 'true'
|
||||
|
||||
if (!process.env.ETH_MAINNET_TEST_RPC) throw ErrorUtils.getError('need a mainnet rpc endpoint.')
|
||||
@ -34,9 +41,7 @@ describe('main', () => {
|
||||
? new TorProvider(process.env.ETH_MAINNET_TEST_RPC, { port: +process.env.TOR_PORT! })
|
||||
: new providers.JsonRpcProvider(process.env.ETH_MAINNET_TEST_RPC)
|
||||
|
||||
const ganacheProvider = new providers.Web3Provider(
|
||||
// @ts-ignore
|
||||
ganache.provider({
|
||||
const _ganacheProvider = ganache.provider({
|
||||
chain: { chainId: 1 },
|
||||
// @ts-ignore
|
||||
fork: { url: process.env.ETH_MAINNET_TEST_RPC },
|
||||
@ -46,7 +51,9 @@ describe('main', () => {
|
||||
unlockedAccounts: [daiWhale]
|
||||
}
|
||||
})
|
||||
)
|
||||
|
||||
// @ts-expect-error
|
||||
const ganacheProvider = new providers.Web3Provider(_ganacheProvider)
|
||||
const chain = new Chain(ganacheProvider)
|
||||
|
||||
let snapshotId: any
|
||||
@ -57,7 +64,7 @@ describe('main', () => {
|
||||
})
|
||||
|
||||
describe('namespace Tornado', () => {
|
||||
describe('namespace Contracts', () => {
|
||||
describe.skip('namespace Contracts', () => {
|
||||
it('getClassicInstance: should be able to get a tornado instance', async () => {
|
||||
let instance = await Contracts.getInstance(String(1), 'eth', String(1), mainnetProvider)
|
||||
expect(instance.address).to.equal('0x47CE0C6eD5B0Ce3d3A51fdb1C52DC66a7c3c2936')
|
||||
@ -66,17 +73,17 @@ describe('main', () => {
|
||||
})
|
||||
|
||||
describe('class Classic', () => {
|
||||
it('sync: should be able to fetch a couple events', async () => {
|
||||
it.skip('sync: Should be able to fetch deposit events', async () => {
|
||||
const core = new Core(mainnetProvider)
|
||||
const instance = await Contracts.getInstance(String(1), 'eth', String(0.1), mainnetProvider)
|
||||
const targetBlock = 16928712
|
||||
const startBlock = targetBlock - 7200
|
||||
//const targetBlock = 16928712
|
||||
//const startBlock = targetBlock - 7200
|
||||
await core.sync(instance, {
|
||||
//deposit: true,
|
||||
//withdrawal: false,
|
||||
blocks: {
|
||||
startBlock: startBlock,
|
||||
targetBlock: targetBlock
|
||||
//startBlock: startBlock,
|
||||
//targetBlock: targetBlock
|
||||
},
|
||||
cache: {
|
||||
sync: {
|
||||
@ -84,6 +91,21 @@ describe('main', () => {
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
const cache = core.caches.get('Deposits1ETH0.1')
|
||||
const rows = (await cache!.db.allDocs()).rows
|
||||
const valid = Object.values(compareDeposits)
|
||||
|
||||
expect(rows.length).to.be.gte(valid.length)
|
||||
|
||||
for (let i = 0, len = valid.length; i < len; i++) {
|
||||
const id = rows[i].id
|
||||
const [bn, leafIndex, commitment] = parseIndexableString(id)
|
||||
const validDoc = valid[i]
|
||||
expect(bn).to.equal(validDoc['blockNumber'])
|
||||
expect(leafIndex).to.equal(validDoc['leafIndex'])
|
||||
expect(commitment).to.equal(validDoc['commitment'])
|
||||
}
|
||||
}).timeout(0)
|
||||
|
||||
describe('ganache fork', async () => {
|
||||
@ -93,6 +115,8 @@ describe('main', () => {
|
||||
|
||||
let needsMoneyAddress: string
|
||||
let dai: ERC20
|
||||
let smallestEth: TornadoInstance
|
||||
let note: ZKDepositData, noteObj: any
|
||||
|
||||
before(async function () {
|
||||
this.timeout(0)
|
||||
@ -102,6 +126,7 @@ describe('main', () => {
|
||||
needsMoneyAddress = await needsMoney.getAddress()
|
||||
daiData = await OnchainData.getTokenData('1', 'dai')
|
||||
dai = chain.getTokenContract(daiData.address).connect(whale)
|
||||
smallestEth = await core.getInstance('eth', 0.1)
|
||||
})
|
||||
after(async function () {
|
||||
this.timeout(0)
|
||||
@ -112,20 +137,72 @@ describe('main', () => {
|
||||
dai = dai.connect(whale)
|
||||
})
|
||||
|
||||
it('buildDepositTx: build a single eth deposit tx and succeed', async () => {
|
||||
it.only('buildDepositTx: build a single eth deposit tx and succeed', async () => {
|
||||
const signer = ganacheProvider.getSigner()
|
||||
const initBal = await signer.getBalance()
|
||||
|
||||
const tx = await core.buildDepositTx(await core.getInstance('eth', 100))
|
||||
await signer.sendTransaction(tx.request)
|
||||
const tx = await core.buildDepositTx(smallestEth)
|
||||
const response = await signer.sendTransaction(tx.request)
|
||||
const receipt = await response.wait()
|
||||
|
||||
noteObj = {
|
||||
blockNumber: receipt.blockNumber,
|
||||
transactionHash: receipt.transactionHash,
|
||||
args: {
|
||||
commitment: '',
|
||||
leafIndex: 0,
|
||||
timestamp: response.timestamp
|
||||
}
|
||||
}
|
||||
|
||||
console.log(receipt, '\n')
|
||||
|
||||
note = Primitives.parseNote(tx.note!)
|
||||
|
||||
const endBal = await signer.getBalance()
|
||||
|
||||
expect(initBal).to.equal(parseUnits('1000'))
|
||||
expect(endBal).to.be.lte(parseUnits('900'))
|
||||
expect(endBal).to.be.lte(parseUnits('999.9'))
|
||||
}).timeout(0)
|
||||
|
||||
it('buildDepositTx: build a single token deposit tx and succeed', async () => {
|
||||
it.only('buildDepositProofs: it should be able to build', async () => {
|
||||
try {
|
||||
const instance = await core.getInstance('eth', 0.1)
|
||||
const signer = ganacheProvider.getSigner()
|
||||
const withdrawer = ganacheProvider.getSigner(2)
|
||||
|
||||
const cache = core.loadCache('Deposits1ETH0.1') as Cache.Base<Docs.Deposit>
|
||||
|
||||
noteObj['args'] = {
|
||||
commitment: note.hexCommitment,
|
||||
leafIndex: (await cache!.db.allDocs({ descending: true, limit: 1, include_docs: true }))
|
||||
?.rows[0].doc?.leafIndex,
|
||||
timestamp: noteObj['args']['timestamp']
|
||||
}
|
||||
|
||||
console.log(noteObj, '\n')
|
||||
|
||||
await cache!.db.put(new Docs.Deposit(noteObj))
|
||||
|
||||
console.log(`\nBuilding proof from note:\n\n${note}\n\n`)
|
||||
|
||||
const proof = await core.buildDepositProof(
|
||||
instance,
|
||||
{
|
||||
address: await withdrawer.getAddress()
|
||||
},
|
||||
await signer.getAddress(),
|
||||
note
|
||||
)
|
||||
|
||||
console.log(proof)
|
||||
} catch (err) {
|
||||
console.log(ErrorUtils.ensureError(err).message)
|
||||
throw err
|
||||
}
|
||||
}).timeout(0)
|
||||
|
||||
it.skip('buildDepositTx: build a single token deposit tx and succeed', async () => {
|
||||
const dai100K = await core.getInstance('dai', 100000)
|
||||
const proxy = await core.getProxy()
|
||||
const depositAmount = parseUnits('100000')
|
||||
@ -142,7 +219,7 @@ describe('main', () => {
|
||||
expect(await dai.balanceOf(needsMoneyAddress)).to.equal(0)
|
||||
}).timeout(0)
|
||||
|
||||
it('buildDepositTxs: multiple eth deposits', async () => {
|
||||
it.skip('buildDepositTxs: multiple eth deposits', async () => {
|
||||
const instances = await core.getInstances(
|
||||
[0.1, 1, 10, 100].map((el) => {
|
||||
return { token: 'eth', denomination: el }
|
||||
@ -159,7 +236,7 @@ describe('main', () => {
|
||||
expect(await dai.balanceOf(needsMoneyAddress)).to.equal(0)
|
||||
}).timeout(0)
|
||||
|
||||
it('buildDepositTxs: multiple token deposits', async () => {
|
||||
it.skip('buildDepositTxs: multiple token deposits', async () => {
|
||||
const instances = await core.getInstances(
|
||||
[100, 1000, 10000, 100000].map((el) => {
|
||||
return { token: 'dai', denomination: el }
|
||||
@ -185,7 +262,7 @@ describe('main', () => {
|
||||
expect(await dai.balanceOf(needsMoneyAddress)).to.equal(0)
|
||||
}).timeout(0)
|
||||
|
||||
it('createInvoice: should be able to create an invoice', async () => {
|
||||
it.skip('createInvoice: should be able to create an invoice', async () => {
|
||||
const instance = await core.getInstance('dai', '1000')
|
||||
const invoice = await core.createInvoice(instance)
|
||||
console.log(invoice)
|
||||
|
193811
src/test/resources/deposits_eth_0.1.json
Normal file
193811
src/test/resources/deposits_eth_0.1.json
Normal file
File diff suppressed because it is too large
Load Diff
@ -18,6 +18,7 @@ describe('web', () => {
|
||||
const torProvider = new TorProvider(process.env.ETH_MAINNET_TEST_RPC, { port: +process.env.TOR_PORT })
|
||||
const httpClient = new TorHttpClient({ port: +process.env.TOR_PORT })
|
||||
|
||||
if (process.env.TORIFY === 'true')
|
||||
console.log(
|
||||
'\nSome Tor tips: Support non-profit exit node operators, host your own nodes, avoid spy nodes by configuring torrc.\n'
|
||||
)
|
||||
@ -41,7 +42,7 @@ describe('web', () => {
|
||||
}
|
||||
}).timeout(0)
|
||||
|
||||
it.only('TorProvider: Should be able to fetch some basic blockchain data over Tor', async () => {
|
||||
it('TorProvider: Should be able to fetch some basic blockchain data over Tor', async () => {
|
||||
try {
|
||||
console.log('\nBlock Number: ' + (await torProvider.getBlockNumber()))
|
||||
console.log('Gas Price: ' + (await torProvider.getGasPrice()).div(1000000000) + ' gwei')
|
||||
@ -55,7 +56,7 @@ describe('web', () => {
|
||||
}
|
||||
}).timeout(0)
|
||||
|
||||
it.skip('DISCONNECTED: Should not be able to request over Tor', async function () {
|
||||
it('DISCONNECTED: Should not be able to request over Tor', async function () {
|
||||
try {
|
||||
await torProvider.getBlockNumber()
|
||||
throw ErrorUtils.getError('should not have succeeded.')
|
||||
|
@ -7,7 +7,6 @@
|
||||
|
||||
import { TransactionRequest } from '@ethersproject/abstract-provider'
|
||||
import { BigNumber } from 'ethers'
|
||||
import { RelayerProperties as RelayerDataProperties } from 'types/sdk/data'
|
||||
|
||||
export namespace Options {
|
||||
export namespace Cache {
|
||||
@ -48,9 +47,13 @@ export namespace Options {
|
||||
export type Invoice = Deposit
|
||||
|
||||
export interface BuildDepositProof {
|
||||
gasPrice?: BigNumber
|
||||
gasPriceCushion?: BigNumber
|
||||
tokenDecimals?: number
|
||||
ethPurchaseAmounts?: Array<BigNumber>
|
||||
merkleTreeHeight?: number
|
||||
checkNotesSpent?: boolean
|
||||
checkKnownRoot?: boolean
|
||||
merkleTreeHeight?: number
|
||||
}
|
||||
}
|
||||
}
|
@ -34,9 +34,9 @@ export namespace OutputOf {
|
||||
}
|
||||
|
||||
export interface Groth16Proof {
|
||||
pi_a: Array<string>
|
||||
pi_b: Array<string>
|
||||
pi_c: Array<string>
|
||||
pi_a: string
|
||||
pi_b: string
|
||||
pi_c: string
|
||||
}
|
||||
}
|
||||
|
||||
@ -50,6 +50,7 @@ type __OutputAliasDelimiter = null
|
||||
|
||||
export type MerkleProof = OutputOf.MerkleProof
|
||||
export type ZKProof = OutputOf.Groth16Proof
|
||||
export type DepositProof = OutputOf.Groth16Proof
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ INPUTS ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
/**
|
||||
@ -82,8 +83,8 @@ export namespace InputFor {
|
||||
hexNullifierHash: string
|
||||
recipientAddress: string
|
||||
relayerAddress: string
|
||||
fee: number
|
||||
refund: number
|
||||
fee: bigInt
|
||||
refund: bigInt
|
||||
}
|
||||
private: {
|
||||
nullifier: bigInt
|
||||
@ -104,7 +105,7 @@ export namespace InputFor {
|
||||
nullifier: bigInt
|
||||
secret: bigInt
|
||||
pathIndices: number[]
|
||||
pathElements: any[]
|
||||
pathElements: string[]
|
||||
}
|
||||
|
||||
export type Groth16 = PublicGroth16 & PrivateGroth16
|
||||
|
@ -1,49 +1,4 @@
|
||||
import { isAddress } from 'ethers/lib/utils'
|
||||
import { ErrorUtils } from 'lib/utils'
|
||||
|
||||
// TODO: Decide whether to really use below, possibly from external interface
|
||||
|
||||
type NetworkId = string | number
|
||||
type TokenId = string
|
||||
type ContractId = string
|
||||
type Denomination = number
|
||||
|
||||
class DataKey<T extends TokenId | NetworkId | ContractId | Denomination> {
|
||||
value: string
|
||||
isAddress?: boolean
|
||||
isSymbol?: boolean
|
||||
isName?: boolean
|
||||
|
||||
constructor(id: T) {
|
||||
this.value = this._validate(id)
|
||||
}
|
||||
|
||||
private _validate(id: T): string {
|
||||
let type = typeof id
|
||||
switch (type) {
|
||||
case 'string':
|
||||
let val = id as string
|
||||
|
||||
if (isAddress(val)) {
|
||||
this.isAddress = true
|
||||
return val
|
||||
} else {
|
||||
this.isSymbol = true
|
||||
this.isName = true
|
||||
}
|
||||
return val.toLowerCase()
|
||||
case 'number':
|
||||
return String(id)
|
||||
default:
|
||||
throw ErrorUtils.getError(`unsupported key type ${type}.`)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type NetworkKey = DataKey<NetworkId>
|
||||
type TokenKey = DataKey<TokenId>
|
||||
type ContractKey = DataKey<ContractId>
|
||||
type DenominationKey = DataKey<Denomination>
|
||||
import { BigNumber } from 'ethers'
|
||||
|
||||
export namespace Json {
|
||||
export interface TornadoInstance {
|
||||
@ -81,4 +36,5 @@ export interface RelayerProperties {
|
||||
miningFeePercent: number
|
||||
status: string
|
||||
chainId: number
|
||||
prices: Map<string, BigNumber>
|
||||
}
|
||||
|
@ -1,7 +1,16 @@
|
||||
import { AxiosInstance } from 'axios'
|
||||
|
||||
export interface RelayerOptions {
|
||||
export namespace Relayer {
|
||||
export interface Options {
|
||||
url: string
|
||||
address?: string
|
||||
httpClient: AxiosInstance
|
||||
}
|
||||
|
||||
export interface WithdrawalRequestResult {
|
||||
success: boolean
|
||||
txHash?: string
|
||||
}
|
||||
}
|
||||
|
||||
export type RelayerOptions = Relayer.Options
|
||||
|
@ -6,20 +6,23 @@
|
||||
"require": ["tsconfig-paths/register"]
|
||||
},
|
||||
"compilerOptions": {
|
||||
"target": "es2017",
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~NODE 18 STANDARD~~~~~~~~~~~~~~~~~~~~~~~
|
||||
"target": "es2022",
|
||||
"module": "commonjs",
|
||||
"lib": ["es2020"],
|
||||
"lib": ["es2022"],
|
||||
"strict": true,
|
||||
"esModuleInterop": true,
|
||||
"skipLibCheck": true,
|
||||
"moduleResolution": "node",
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
"outDir": "./build",
|
||||
"resolveJsonModule": true,
|
||||
"declaration": true,
|
||||
"declarationMap": true,
|
||||
"sourceMap": true,
|
||||
"moduleResolution": "node",
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"esModuleInterop": true,
|
||||
"strict": true,
|
||||
"checkJs": true,
|
||||
"allowJs": true,
|
||||
"skipLibCheck": true,
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"test/*": ["src/test/*"],
|
||||
|
364
yarn.lock
364
yarn.lock
@ -30,14 +30,26 @@
|
||||
dependencies:
|
||||
"@jridgewell/trace-mapping" "0.3.9"
|
||||
|
||||
"@eslint/eslintrc@^2.0.0":
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.0.0.tgz#943309d8697c52fc82c076e90c1c74fbbe69dbff"
|
||||
integrity sha512-fluIaaV+GyV24CCu/ggiHdV+j4RNh85yQnAYS/G2mZODZgGmmlrgCydjUcV3YvxCm9x8nMAfThsqTni4KiXT4A==
|
||||
"@eslint-community/eslint-utils@^4.2.0":
|
||||
version "4.4.0"
|
||||
resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59"
|
||||
integrity sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==
|
||||
dependencies:
|
||||
eslint-visitor-keys "^3.3.0"
|
||||
|
||||
"@eslint-community/regexpp@^4.4.0":
|
||||
version "4.5.0"
|
||||
resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.5.0.tgz#f6f729b02feee2c749f57e334b7a1b5f40a81724"
|
||||
integrity sha512-vITaYzIcNmjn5tF5uxcZ/ft7/RXGrMUIS9HalWckEOF6ESiwXKoMzAQf2UW0aVd6rnOeExTJVd5hmWXucBKGXQ==
|
||||
|
||||
"@eslint/eslintrc@^2.0.2":
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.0.2.tgz#01575e38707add677cf73ca1589abba8da899a02"
|
||||
integrity sha512-3W4f5tDUra+pA+FzgugqL2pRimUTDJWKr7BINqOpkZrC0uYI0NIc0/JFgBROCU07HR6GieA5m3/rsPIhDmCXTQ==
|
||||
dependencies:
|
||||
ajv "^6.12.4"
|
||||
debug "^4.3.2"
|
||||
espree "^9.4.0"
|
||||
espree "^9.5.1"
|
||||
globals "^13.19.0"
|
||||
ignore "^5.2.0"
|
||||
import-fresh "^3.2.1"
|
||||
@ -45,10 +57,10 @@
|
||||
minimatch "^3.1.2"
|
||||
strip-json-comments "^3.1.1"
|
||||
|
||||
"@eslint/js@8.35.0":
|
||||
version "8.35.0"
|
||||
resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.35.0.tgz#b7569632b0b788a0ca0e438235154e45d42813a7"
|
||||
integrity sha512-JXdzbRiWclLVoD8sNUjR443VVlYqiYmDVT6rGUEIEHU5YJW0gaVZwV2xgM7D4arkvASqD0IlLUVjHiFuxaftRw==
|
||||
"@eslint/js@8.38.0":
|
||||
version "8.38.0"
|
||||
resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.38.0.tgz#73a8a0d8aa8a8e6fe270431c5e72ae91b5337892"
|
||||
integrity sha512-IoD2MfUnOV58ghIHCiil01PcohxjbYR/qCxsoC+xNgUwh1EY8jOOrYmu3d3a71+tJJ23uscEV4X2HJWMsPJu4g==
|
||||
|
||||
"@ethereum-waffle/chai@4.0.10":
|
||||
version "4.0.10"
|
||||
@ -622,14 +634,14 @@
|
||||
integrity sha512-H9XAx3hc0BQHY6l+IFSWHDySypcXsvsuLhgYLUGywmJ5pswRVQJUHpOsobnLYp2ZUaUlKiKDrgWWhosOwAEM8Q==
|
||||
|
||||
"@jridgewell/resolve-uri@^3.0.3":
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78"
|
||||
integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==
|
||||
version "3.1.1"
|
||||
resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz#c08679063f279615a3326583ba3a90d1d82cc721"
|
||||
integrity sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==
|
||||
|
||||
"@jridgewell/sourcemap-codec@^1.4.10":
|
||||
version "1.4.14"
|
||||
resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24"
|
||||
integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==
|
||||
version "1.4.15"
|
||||
resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32"
|
||||
integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==
|
||||
|
||||
"@jridgewell/trace-mapping@0.3.9":
|
||||
version "0.3.9"
|
||||
@ -738,6 +750,16 @@
|
||||
dependencies:
|
||||
node-gyp-build "4.3.0"
|
||||
|
||||
"@trufflesuite/uws-js-unofficial@20.10.0-unofficial.2":
|
||||
version "20.10.0-unofficial.2"
|
||||
resolved "https://registry.yarnpkg.com/@trufflesuite/uws-js-unofficial/-/uws-js-unofficial-20.10.0-unofficial.2.tgz#7ed613ce3260cd5d1773a4d5787a2a106acd1a91"
|
||||
integrity sha512-oQQlnS3oNeGsgS4K3KCSSavJgSb0W9D5ktZs4FacX9VbM7b+NlhjH96d6/G4fMrz+bc5MXRyco419on0X0dvRA==
|
||||
dependencies:
|
||||
ws "8.2.3"
|
||||
optionalDependencies:
|
||||
bufferutil "4.0.5"
|
||||
utf-8-validate "5.0.7"
|
||||
|
||||
"@tsconfig/node10@^1.0.7":
|
||||
version "1.0.9"
|
||||
resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.9.tgz#df4907fc07a886922637b15e02d4cebc4c0021b2"
|
||||
@ -888,14 +910,14 @@
|
||||
integrity sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==
|
||||
|
||||
"@types/node-fetch@^2.6.1":
|
||||
version "2.6.2"
|
||||
resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.6.2.tgz#d1a9c5fd049d9415dce61571557104dec3ec81da"
|
||||
integrity sha512-DHqhlq5jeESLy19TYhLakJ07kNumXWjcDdxXsLUMJZ6ue8VZJj4kLPQVE/2mdHh3xZziNF1xppu5lwmS53HR+A==
|
||||
version "2.6.3"
|
||||
resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.6.3.tgz#175d977f5e24d93ad0f57602693c435c57ad7e80"
|
||||
integrity sha512-ETTL1mOEdq/sxUtgtOhKjyB2Irra4cjxksvcMUR5Zr4n+PxVhsCD9WS46oPbHL3et9Zde7CNRr+WUNlcHvsX+w==
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
form-data "^3.0.0"
|
||||
|
||||
"@types/node@*":
|
||||
"@types/node@*", "@types/node@^18.15.0":
|
||||
version "18.15.11"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-18.15.11.tgz#b3b790f09cb1696cffcec605de025b088fa4225f"
|
||||
integrity sha512-E5Kwq2n4SbMzQOn6wnmBjuK9ouqlURrcZDVfbo9ftDDTFt3nk7ZKK4GMOzoYgnpQJKcxwQw+lGaBvvlMo0qN/Q==
|
||||
@ -910,11 +932,6 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-12.20.55.tgz#c329cbd434c42164f846b909bd6f85b5537f6240"
|
||||
integrity sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==
|
||||
|
||||
"@types/node@^18.15.0":
|
||||
version "18.15.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-18.15.0.tgz#286a65e3fdffd691e170541e6ecb0410b16a38be"
|
||||
integrity sha512-z6nr0TTEOBGkzLGmbypWOGnpSpSIBorEhC4L+4HeQ2iezKCi4f77kyslRwvHeNitymGQ+oFyIWGP96l/DPSV9w==
|
||||
|
||||
"@types/normalize-package-data@^2.4.0":
|
||||
version "2.4.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz#d3357479a0fdfdd5907fe67e17e0a85c906e1301"
|
||||
@ -1103,87 +1120,87 @@
|
||||
integrity sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==
|
||||
|
||||
"@typescript-eslint/eslint-plugin@^5.54.1":
|
||||
version "5.54.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.54.1.tgz#0c5091289ce28372e38ab8d28e861d2dbe1ab29e"
|
||||
integrity sha512-a2RQAkosH3d3ZIV08s3DcL/mcGc2M/UC528VkPULFxR9VnVPT8pBu0IyBAJJmVsCmhVfwQX1v6q+QGnmSe1bew==
|
||||
version "5.58.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.58.0.tgz#b1d4b0ad20243269d020ef9bbb036a40b0849829"
|
||||
integrity sha512-vxHvLhH0qgBd3/tW6/VccptSfc8FxPQIkmNTVLWcCOVqSBvqpnKkBTYrhcGlXfSnd78azwe+PsjYFj0X34/njA==
|
||||
dependencies:
|
||||
"@typescript-eslint/scope-manager" "5.54.1"
|
||||
"@typescript-eslint/type-utils" "5.54.1"
|
||||
"@typescript-eslint/utils" "5.54.1"
|
||||
"@eslint-community/regexpp" "^4.4.0"
|
||||
"@typescript-eslint/scope-manager" "5.58.0"
|
||||
"@typescript-eslint/type-utils" "5.58.0"
|
||||
"@typescript-eslint/utils" "5.58.0"
|
||||
debug "^4.3.4"
|
||||
grapheme-splitter "^1.0.4"
|
||||
ignore "^5.2.0"
|
||||
natural-compare-lite "^1.4.0"
|
||||
regexpp "^3.2.0"
|
||||
semver "^7.3.7"
|
||||
tsutils "^3.21.0"
|
||||
|
||||
"@typescript-eslint/parser@^5.54.1":
|
||||
version "5.54.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.54.1.tgz#05761d7f777ef1c37c971d3af6631715099b084c"
|
||||
integrity sha512-8zaIXJp/nG9Ff9vQNh7TI+C3nA6q6iIsGJ4B4L6MhZ7mHnTMR4YP5vp2xydmFXIy8rpyIVbNAG44871LMt6ujg==
|
||||
version "5.58.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.58.0.tgz#2ac4464cf48bef2e3234cb178ede5af352dddbc6"
|
||||
integrity sha512-ixaM3gRtlfrKzP8N6lRhBbjTow1t6ztfBvQNGuRM8qH1bjFFXIJ35XY+FC0RRBKn3C6cT+7VW1y8tNm7DwPHDQ==
|
||||
dependencies:
|
||||
"@typescript-eslint/scope-manager" "5.54.1"
|
||||
"@typescript-eslint/types" "5.54.1"
|
||||
"@typescript-eslint/typescript-estree" "5.54.1"
|
||||
"@typescript-eslint/scope-manager" "5.58.0"
|
||||
"@typescript-eslint/types" "5.58.0"
|
||||
"@typescript-eslint/typescript-estree" "5.58.0"
|
||||
debug "^4.3.4"
|
||||
|
||||
"@typescript-eslint/scope-manager@5.54.1":
|
||||
version "5.54.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.54.1.tgz#6d864b4915741c608a58ce9912edf5a02bb58735"
|
||||
integrity sha512-zWKuGliXxvuxyM71UA/EcPxaviw39dB2504LqAmFDjmkpO8qNLHcmzlh6pbHs1h/7YQ9bnsO8CCcYCSA8sykUg==
|
||||
"@typescript-eslint/scope-manager@5.58.0":
|
||||
version "5.58.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.58.0.tgz#5e023a48352afc6a87be6ce3c8e763bc9e2f0bc8"
|
||||
integrity sha512-b+w8ypN5CFvrXWQb9Ow9T4/6LC2MikNf1viLkYTiTbkQl46CnR69w7lajz1icW0TBsYmlpg+mRzFJ4LEJ8X9NA==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "5.54.1"
|
||||
"@typescript-eslint/visitor-keys" "5.54.1"
|
||||
"@typescript-eslint/types" "5.58.0"
|
||||
"@typescript-eslint/visitor-keys" "5.58.0"
|
||||
|
||||
"@typescript-eslint/type-utils@5.54.1":
|
||||
version "5.54.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.54.1.tgz#4825918ec27e55da8bb99cd07ec2a8e5f50ab748"
|
||||
integrity sha512-WREHsTz0GqVYLIbzIZYbmUUr95DKEKIXZNH57W3s+4bVnuF1TKe2jH8ZNH8rO1CeMY3U4j4UQeqPNkHMiGem3g==
|
||||
"@typescript-eslint/type-utils@5.58.0":
|
||||
version "5.58.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.58.0.tgz#f7d5b3971483d4015a470d8a9e5b8a7d10066e52"
|
||||
integrity sha512-FF5vP/SKAFJ+LmR9PENql7fQVVgGDOS+dq3j+cKl9iW/9VuZC/8CFmzIP0DLKXfWKpRHawJiG70rVH+xZZbp8w==
|
||||
dependencies:
|
||||
"@typescript-eslint/typescript-estree" "5.54.1"
|
||||
"@typescript-eslint/utils" "5.54.1"
|
||||
"@typescript-eslint/typescript-estree" "5.58.0"
|
||||
"@typescript-eslint/utils" "5.58.0"
|
||||
debug "^4.3.4"
|
||||
tsutils "^3.21.0"
|
||||
|
||||
"@typescript-eslint/types@5.54.1":
|
||||
version "5.54.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.54.1.tgz#29fbac29a716d0f08c62fe5de70c9b6735de215c"
|
||||
integrity sha512-G9+1vVazrfAfbtmCapJX8jRo2E4MDXxgm/IMOF4oGh3kq7XuK3JRkOg6y2Qu1VsTRmWETyTkWt1wxy7X7/yLkw==
|
||||
"@typescript-eslint/types@5.58.0":
|
||||
version "5.58.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.58.0.tgz#54c490b8522c18986004df7674c644ffe2ed77d8"
|
||||
integrity sha512-JYV4eITHPzVQMnHZcYJXl2ZloC7thuUHrcUmxtzvItyKPvQ50kb9QXBkgNAt90OYMqwaodQh2kHutWZl1fc+1g==
|
||||
|
||||
"@typescript-eslint/typescript-estree@5.54.1":
|
||||
version "5.54.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.54.1.tgz#df7b6ae05fd8fef724a87afa7e2f57fa4a599be1"
|
||||
integrity sha512-bjK5t+S6ffHnVwA0qRPTZrxKSaFYocwFIkZx5k7pvWfsB1I57pO/0M0Skatzzw1sCkjJ83AfGTL0oFIFiDX3bg==
|
||||
"@typescript-eslint/typescript-estree@5.58.0":
|
||||
version "5.58.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.58.0.tgz#4966e6ff57eaf6e0fce2586497edc097e2ab3e61"
|
||||
integrity sha512-cRACvGTodA+UxnYM2uwA2KCwRL7VAzo45syNysqlMyNyjw0Z35Icc9ihPJZjIYuA5bXJYiJ2YGUB59BqlOZT1Q==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "5.54.1"
|
||||
"@typescript-eslint/visitor-keys" "5.54.1"
|
||||
"@typescript-eslint/types" "5.58.0"
|
||||
"@typescript-eslint/visitor-keys" "5.58.0"
|
||||
debug "^4.3.4"
|
||||
globby "^11.1.0"
|
||||
is-glob "^4.0.3"
|
||||
semver "^7.3.7"
|
||||
tsutils "^3.21.0"
|
||||
|
||||
"@typescript-eslint/utils@5.54.1":
|
||||
version "5.54.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.54.1.tgz#7a3ee47409285387b9d4609ea7e1020d1797ec34"
|
||||
integrity sha512-IY5dyQM8XD1zfDe5X8jegX6r2EVU5o/WJnLu/znLPWCBF7KNGC+adacXnt5jEYS9JixDcoccI6CvE4RCjHMzCQ==
|
||||
"@typescript-eslint/utils@5.58.0":
|
||||
version "5.58.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.58.0.tgz#430d7c95f23ec457b05be5520c1700a0dfd559d5"
|
||||
integrity sha512-gAmLOTFXMXOC+zP1fsqm3VceKSBQJNzV385Ok3+yzlavNHZoedajjS4UyS21gabJYcobuigQPs/z71A9MdJFqQ==
|
||||
dependencies:
|
||||
"@eslint-community/eslint-utils" "^4.2.0"
|
||||
"@types/json-schema" "^7.0.9"
|
||||
"@types/semver" "^7.3.12"
|
||||
"@typescript-eslint/scope-manager" "5.54.1"
|
||||
"@typescript-eslint/types" "5.54.1"
|
||||
"@typescript-eslint/typescript-estree" "5.54.1"
|
||||
"@typescript-eslint/scope-manager" "5.58.0"
|
||||
"@typescript-eslint/types" "5.58.0"
|
||||
"@typescript-eslint/typescript-estree" "5.58.0"
|
||||
eslint-scope "^5.1.1"
|
||||
eslint-utils "^3.0.0"
|
||||
semver "^7.3.7"
|
||||
|
||||
"@typescript-eslint/visitor-keys@5.54.1":
|
||||
version "5.54.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.54.1.tgz#d7a8a0f7181d6ac748f4d47b2306e0513b98bf8b"
|
||||
integrity sha512-q8iSoHTgwCfgcRJ2l2x+xCbu8nBlRAlsQ33k24Adj8eoVBE0f8dUeI+bAa8F84Mv05UGbAx57g2zrRsYIooqQg==
|
||||
"@typescript-eslint/visitor-keys@5.58.0":
|
||||
version "5.58.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.58.0.tgz#eb9de3a61d2331829e6761ce7fd13061781168b4"
|
||||
integrity sha512-/fBraTlPj0jwdyTwLyrRTxv/3lnU2H96pNTVM6z3esTWLtA5MZ9ghSMJ7Rb+TtUAdtEw9EyJzJ0EydIMKxQ9gA==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "5.54.1"
|
||||
"@typescript-eslint/types" "5.58.0"
|
||||
eslint-visitor-keys "^3.3.0"
|
||||
|
||||
"@uniswap/default-token-list@^9.3.0":
|
||||
@ -2241,9 +2258,9 @@ cookiejar@^2.1.1:
|
||||
integrity sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==
|
||||
|
||||
core-js-pure@^3.0.1:
|
||||
version "3.29.1"
|
||||
resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.29.1.tgz#1be6ca2b8772f6b4df7fc4621743286e676c6162"
|
||||
integrity sha512-4En6zYVi0i0XlXHVz/bi6l1XDjCqkKRq765NXuX+SnaIatlE96Odt5lMLjdxUiNI1v9OXI5DSLWYPlmTfkTktg==
|
||||
version "3.30.1"
|
||||
resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.30.1.tgz#7d93dc89e7d47b8ef05d7e79f507b0e99ea77eec"
|
||||
integrity sha512-nXBEVpmUnNRhz83cHd9JRQC52cTMcuXAmR56+9dSMpRdpeA4I1PX6yjmhd71Eyc/wXNsdBdUDIj1QTIeZpU5Tg==
|
||||
|
||||
core-util-is@1.0.2:
|
||||
version "1.0.2"
|
||||
@ -2656,9 +2673,9 @@ eslint-scope@^5.1.1:
|
||||
estraverse "^4.1.1"
|
||||
|
||||
eslint-scope@^7.1.1:
|
||||
version "7.1.1"
|
||||
resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.1.1.tgz#fff34894c2f65e5226d3041ac480b4513a163642"
|
||||
integrity sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==
|
||||
version "7.2.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.2.0.tgz#f21ebdafda02352f103634b96dd47d9f81ca117b"
|
||||
integrity sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw==
|
||||
dependencies:
|
||||
esrecurse "^4.3.0"
|
||||
estraverse "^5.2.0"
|
||||
@ -2670,27 +2687,15 @@ eslint-utils@^1.3.1:
|
||||
dependencies:
|
||||
eslint-visitor-keys "^1.1.0"
|
||||
|
||||
eslint-utils@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-3.0.0.tgz#8aebaface7345bb33559db0a1f13a1d2d48c3672"
|
||||
integrity sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==
|
||||
dependencies:
|
||||
eslint-visitor-keys "^2.0.0"
|
||||
|
||||
eslint-visitor-keys@^1.0.0, eslint-visitor-keys@^1.1.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e"
|
||||
integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==
|
||||
|
||||
eslint-visitor-keys@^2.0.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303"
|
||||
integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==
|
||||
|
||||
eslint-visitor-keys@^3.3.0:
|
||||
version "3.3.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz#f6480fa6b1f30efe2d1968aa8ac745b862469826"
|
||||
integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==
|
||||
eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.0:
|
||||
version "3.4.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.0.tgz#c7f0f956124ce677047ddbc192a68f999454dedc"
|
||||
integrity sha512-HPpKPUBQcAsZOsHAFwTtIKcYlCje62XB7SEAcxjtmW6TD1WVpkS6i6/hOVtTZIl4zGj/mBqpFVGvaDneik+VoQ==
|
||||
|
||||
eslint@^5.16.0:
|
||||
version "5.16.0"
|
||||
@ -2735,12 +2740,14 @@ eslint@^5.16.0:
|
||||
text-table "^0.2.0"
|
||||
|
||||
eslint@^8.35.0:
|
||||
version "8.35.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.35.0.tgz#fffad7c7e326bae606f0e8f436a6158566d42323"
|
||||
integrity sha512-BxAf1fVL7w+JLRQhWl2pzGeSiGqbWumV4WNvc9Rhp6tiCtm4oHnyPBSEtMGZwrQgudFQ+otqzWoPB7x+hxoWsw==
|
||||
version "8.38.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.38.0.tgz#a62c6f36e548a5574dd35728ac3c6209bd1e2f1a"
|
||||
integrity sha512-pIdsD2jwlUGf/U38Jv97t8lq6HpaU/G9NKbYmpWpZGw3LdTNhZLbJePqxOXGB5+JEKfOPU/XLxYxFh03nr1KTg==
|
||||
dependencies:
|
||||
"@eslint/eslintrc" "^2.0.0"
|
||||
"@eslint/js" "8.35.0"
|
||||
"@eslint-community/eslint-utils" "^4.2.0"
|
||||
"@eslint-community/regexpp" "^4.4.0"
|
||||
"@eslint/eslintrc" "^2.0.2"
|
||||
"@eslint/js" "8.38.0"
|
||||
"@humanwhocodes/config-array" "^0.11.8"
|
||||
"@humanwhocodes/module-importer" "^1.0.1"
|
||||
"@nodelib/fs.walk" "^1.2.8"
|
||||
@ -2751,9 +2758,8 @@ eslint@^8.35.0:
|
||||
doctrine "^3.0.0"
|
||||
escape-string-regexp "^4.0.0"
|
||||
eslint-scope "^7.1.1"
|
||||
eslint-utils "^3.0.0"
|
||||
eslint-visitor-keys "^3.3.0"
|
||||
espree "^9.4.0"
|
||||
eslint-visitor-keys "^3.4.0"
|
||||
espree "^9.5.1"
|
||||
esquery "^1.4.2"
|
||||
esutils "^2.0.2"
|
||||
fast-deep-equal "^3.1.3"
|
||||
@ -2775,7 +2781,6 @@ eslint@^8.35.0:
|
||||
minimatch "^3.1.2"
|
||||
natural-compare "^1.4.0"
|
||||
optionator "^0.9.1"
|
||||
regexpp "^3.2.0"
|
||||
strip-ansi "^6.0.1"
|
||||
strip-json-comments "^3.1.0"
|
||||
text-table "^0.2.0"
|
||||
@ -2789,14 +2794,14 @@ espree@^5.0.1:
|
||||
acorn-jsx "^5.0.0"
|
||||
eslint-visitor-keys "^1.0.0"
|
||||
|
||||
espree@^9.4.0:
|
||||
version "9.4.1"
|
||||
resolved "https://registry.yarnpkg.com/espree/-/espree-9.4.1.tgz#51d6092615567a2c2cff7833445e37c28c0065bd"
|
||||
integrity sha512-XwctdmTO6SIvCzd9810yyNzIrOrqNYV9Koizx4C/mRhf9uq0o4yHoCEU/670pOxOL/MSraektvSAji79kX90Vg==
|
||||
espree@^9.5.1:
|
||||
version "9.5.1"
|
||||
resolved "https://registry.yarnpkg.com/espree/-/espree-9.5.1.tgz#4f26a4d5f18905bf4f2e0bd99002aab807e96dd4"
|
||||
integrity sha512-5yxtHSZXRSW5pvv3hAlXM5+/Oswi1AUFqBmbibKb5s6bp3rGIDkyXU6xCoyuuLhijr4SFwPrXRoZjz0AZDN9tg==
|
||||
dependencies:
|
||||
acorn "^8.8.0"
|
||||
acorn-jsx "^5.3.2"
|
||||
eslint-visitor-keys "^3.3.0"
|
||||
eslint-visitor-keys "^3.4.0"
|
||||
|
||||
esprima@^4.0.0:
|
||||
version "4.0.1"
|
||||
@ -3328,9 +3333,9 @@ fresh@0.5.2:
|
||||
integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==
|
||||
|
||||
fs-extra@^11.1.0:
|
||||
version "11.1.0"
|
||||
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-11.1.0.tgz#5784b102104433bb0e090f48bfc4a30742c357ed"
|
||||
integrity sha512-0rcTq621PD5jM/e0a3EJoGC/1TC5ZBCERW82LQuwfGnCa1V8w7dpYH1yNu+SLb6E5dkeCBzKEyLGlFrnr+dUyw==
|
||||
version "11.1.1"
|
||||
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-11.1.1.tgz#da69f7c39f3b002378b0954bb6ae7efdc0876e2d"
|
||||
integrity sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ==
|
||||
dependencies:
|
||||
graceful-fs "^4.2.0"
|
||||
jsonfile "^6.0.1"
|
||||
@ -3399,11 +3404,12 @@ ganache@7.4.3:
|
||||
utf-8-validate "5.0.7"
|
||||
|
||||
ganache@^7.7.7:
|
||||
version "7.7.7"
|
||||
resolved "https://registry.yarnpkg.com/ganache/-/ganache-7.7.7.tgz#19939a86799f0bcb7df02e88082944466394b913"
|
||||
integrity sha512-kZUuOcgDQBtbxzs4iB3chg1iAc28s2ffdOdzyTTzo4vr9sb843w4PbWd5v1hsIqtcNjurcpLaW8XRp/cw2u++g==
|
||||
version "7.8.0"
|
||||
resolved "https://registry.yarnpkg.com/ganache/-/ganache-7.8.0.tgz#02154384f246b66e98974cbcbb18e8372df3c2e0"
|
||||
integrity sha512-IrUYvsaE/m2/NaVIZ7D/gCnsmyU/buechnH6MhUipzG1qJcZIwIp/DoP/LZUcHyhy0Bv0NKZD2pGOjpRhn7l7A==
|
||||
dependencies:
|
||||
"@trufflesuite/bigint-buffer" "1.1.10"
|
||||
"@trufflesuite/uws-js-unofficial" "20.10.0-unofficial.2"
|
||||
"@types/bn.js" "^5.1.0"
|
||||
"@types/lru-cache" "5.1.1"
|
||||
"@types/seedrandom" "3.0.1"
|
||||
@ -3563,12 +3569,12 @@ glob@^7.1.2, glob@^7.1.3:
|
||||
path-is-absolute "^1.0.0"
|
||||
|
||||
glob@^9.2.0:
|
||||
version "9.2.1"
|
||||
resolved "https://registry.yarnpkg.com/glob/-/glob-9.2.1.tgz#f47e34e1119e7d4f93a546e75851ba1f1e68de50"
|
||||
integrity sha512-Pxxgq3W0HyA3XUvSXcFhRSs+43Jsx0ddxcFrbjxNGkL2Ak5BAUBxLqI5G6ADDeCHLfzzXFhe0b1yYcctGmytMA==
|
||||
version "9.3.5"
|
||||
resolved "https://registry.yarnpkg.com/glob/-/glob-9.3.5.tgz#ca2ed8ca452781a3009685607fdf025a899dfe21"
|
||||
integrity sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q==
|
||||
dependencies:
|
||||
fs.realpath "^1.0.0"
|
||||
minimatch "^7.4.1"
|
||||
minimatch "^8.0.2"
|
||||
minipass "^4.2.4"
|
||||
path-scurry "^1.6.1"
|
||||
|
||||
@ -3647,16 +3653,11 @@ got@^11.8.5:
|
||||
p-cancelable "^2.0.0"
|
||||
responselike "^2.0.0"
|
||||
|
||||
graceful-fs@^4.1.2, graceful-fs@^4.1.6:
|
||||
graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0:
|
||||
version "4.2.11"
|
||||
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3"
|
||||
integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==
|
||||
|
||||
graceful-fs@^4.2.0:
|
||||
version "4.2.10"
|
||||
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c"
|
||||
integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==
|
||||
|
||||
grapheme-splitter@^1.0.4:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz#9cf3a665c6247479896834af35cf1dbb4400767e"
|
||||
@ -3949,10 +3950,10 @@ is-callable@^1.1.3:
|
||||
resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055"
|
||||
integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==
|
||||
|
||||
is-core-module@^2.5.0, is-core-module@^2.9.0:
|
||||
version "2.11.0"
|
||||
resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.11.0.tgz#ad4cb3e3863e814523c96f3f58d26cc570ff0144"
|
||||
integrity sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==
|
||||
is-core-module@^2.12.0, is-core-module@^2.5.0:
|
||||
version "2.12.0"
|
||||
resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.12.0.tgz#36ad62f6f73c8253fd6472517a12483cf03e7ec4"
|
||||
integrity sha512-RECHCBCd/viahWmwj6enj19sKbHfJrddi/6cBDsNTKbNq0f7VeaUkBo60BqzvPqo/W54ChS62Z5qyun7cfOMqQ==
|
||||
dependencies:
|
||||
has "^1.0.3"
|
||||
|
||||
@ -4086,9 +4087,9 @@ isstream@~0.1.2:
|
||||
integrity sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==
|
||||
|
||||
js-sdsl@^4.1.4:
|
||||
version "4.3.0"
|
||||
resolved "https://registry.yarnpkg.com/js-sdsl/-/js-sdsl-4.3.0.tgz#aeefe32a451f7af88425b11fdb5f58c90ae1d711"
|
||||
integrity sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==
|
||||
version "4.4.0"
|
||||
resolved "https://registry.yarnpkg.com/js-sdsl/-/js-sdsl-4.4.0.tgz#8b437dbe642daa95760400b602378ed8ffea8430"
|
||||
integrity sha512-FfVSdx6pJ41Oa+CF7RDaFmTnCaFhua+SNYQX74riGOpl96x+2jQCqEfQ2bnXu/5DPCqlRuiqyvTJM0Qjz26IVg==
|
||||
|
||||
js-sha3@0.8.0, js-sha3@^0.8.0:
|
||||
version "0.8.0"
|
||||
@ -4518,10 +4519,10 @@ lru-cache@^6.0.0:
|
||||
dependencies:
|
||||
yallist "^4.0.0"
|
||||
|
||||
lru-cache@^7.14.1:
|
||||
version "7.18.3"
|
||||
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-7.18.3.tgz#f793896e0fd0e954a59dfdd82f0773808df6aa89"
|
||||
integrity sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==
|
||||
lru-cache@^9.0.0:
|
||||
version "9.0.3"
|
||||
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-9.0.3.tgz#8a04f282df5320227bb7215c55df2660d3e4e25b"
|
||||
integrity sha512-cyjNRew29d4kbgnz1sjDqxg7qg8NW4s+HQzCGjeon7DV5T2yDije16W9HaUFV1dhVEMh+SjrOcK0TomBmf3Egg==
|
||||
|
||||
ltgt@2.2.1, ltgt@^2.1.2, ltgt@~2.2.0:
|
||||
version "2.2.1"
|
||||
@ -4740,10 +4741,10 @@ minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2:
|
||||
dependencies:
|
||||
brace-expansion "^1.1.7"
|
||||
|
||||
minimatch@^7.4.1:
|
||||
version "7.4.2"
|
||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-7.4.2.tgz#157e847d79ca671054253b840656720cb733f10f"
|
||||
integrity sha512-xy4q7wou3vUoC9k1xGTXc+awNdGaGVHtFUaey8tiX4H1QRc04DZ/rmDFwNm2EBsuYEhAZ6SgMmYf3InGY6OauA==
|
||||
minimatch@^8.0.2:
|
||||
version "8.0.4"
|
||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-8.0.4.tgz#847c1b25c014d4e9a7f68aaf63dedd668a626229"
|
||||
integrity sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA==
|
||||
dependencies:
|
||||
brace-expansion "^2.0.1"
|
||||
|
||||
@ -4769,10 +4770,15 @@ minipass@^2.6.0, minipass@^2.9.0:
|
||||
safe-buffer "^5.1.2"
|
||||
yallist "^3.0.0"
|
||||
|
||||
minipass@^4.0.2, minipass@^4.2.4:
|
||||
version "4.2.4"
|
||||
resolved "https://registry.yarnpkg.com/minipass/-/minipass-4.2.4.tgz#7d0d97434b6a19f59c5c3221698b48bbf3b2cd06"
|
||||
integrity sha512-lwycX3cBMTvcejsHITUgYj6Gy6A7Nh4Q6h9NP4sTHY1ccJlC7yKzDmiShEHsJ16Jf1nKGDEaiHxiltsJEvk0nQ==
|
||||
minipass@^4.2.4:
|
||||
version "4.2.8"
|
||||
resolved "https://registry.yarnpkg.com/minipass/-/minipass-4.2.8.tgz#f0010f64393ecfc1d1ccb5f582bcaf45f48e1a3a"
|
||||
integrity sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ==
|
||||
|
||||
minipass@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/minipass/-/minipass-5.0.0.tgz#3e9788ffb90b694a5d0ec94479a45b5d8738133d"
|
||||
integrity sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==
|
||||
|
||||
minizlib@^1.3.3:
|
||||
version "1.3.3"
|
||||
@ -5297,12 +5303,12 @@ path-parse@^1.0.7:
|
||||
integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==
|
||||
|
||||
path-scurry@^1.6.1:
|
||||
version "1.6.1"
|
||||
resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.6.1.tgz#dab45f7bb1d3f45a0e271ab258999f4ab7e23132"
|
||||
integrity sha512-OW+5s+7cw6253Q4E+8qQ/u1fVvcJQCJo/VFD8pje+dbJCF1n5ZRMV2AEHbGp+5Q7jxQIYJxkHopnj6nzdGeZLA==
|
||||
version "1.7.0"
|
||||
resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.7.0.tgz#99c741a2cfbce782294a39994d63748b5a24f6db"
|
||||
integrity sha512-UkZUeDjczjYRE495+9thsgcVgsaCPkaw80slmfVFgllxY+IO8ubTsOpFVjDPROBqJdHfVPUFRHPBV/WciOVfWg==
|
||||
dependencies:
|
||||
lru-cache "^7.14.1"
|
||||
minipass "^4.0.2"
|
||||
lru-cache "^9.0.0"
|
||||
minipass "^5.0.0"
|
||||
|
||||
path-to-regexp@0.1.7:
|
||||
version "0.1.7"
|
||||
@ -5542,9 +5548,9 @@ prettier-linter-helpers@^1.0.0:
|
||||
fast-diff "^1.1.2"
|
||||
|
||||
prettier@^2.3.0, prettier@^2.3.1:
|
||||
version "2.8.4"
|
||||
resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.4.tgz#34dd2595629bfbb79d344ac4a91ff948694463c3"
|
||||
integrity sha512-vIS4Rlc2FNh0BySk3Wkd6xmwxB0FpOndW5fisM5H8hsZSxU2VWVB5CWIkIjWvrHjIhxk2g3bfMKM87zNTrZddw==
|
||||
version "2.8.7"
|
||||
resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.7.tgz#bb79fc8729308549d28fe3a98fce73d2c0656450"
|
||||
integrity sha512-yPngTo3aXUUmyuTjeTUT75txrf+aMh9FiD7q9ZE/i6r0bPb22g4FsE6Y338PQX1bmfy08i9QQCB7/rcUAVntfw==
|
||||
|
||||
process-nextick-args@~2.0.0:
|
||||
version "2.0.1"
|
||||
@ -5793,11 +5799,6 @@ regexpp@^2.0.1:
|
||||
resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-2.0.1.tgz#8d19d31cf632482b589049f8281f93dbcba4d07f"
|
||||
integrity sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==
|
||||
|
||||
regexpp@^3.2.0:
|
||||
version "3.2.0"
|
||||
resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2"
|
||||
integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==
|
||||
|
||||
request@^2.79.0, request@^2.85.0:
|
||||
version "2.88.2"
|
||||
resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3"
|
||||
@ -5850,11 +5851,11 @@ resolve-from@^4.0.0:
|
||||
integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==
|
||||
|
||||
resolve@^1.10.0:
|
||||
version "1.22.1"
|
||||
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177"
|
||||
integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==
|
||||
version "1.22.3"
|
||||
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.3.tgz#4b4055349ffb962600972da1fdc33c46a4eb3283"
|
||||
integrity sha512-P8ur/gp/AmbEzjr729bZnLjXK5Z+4P0zhIJgBgzqRih7hL7BOukHGtSTA3ACMY467GRFz3duQsi0bDZdR7DKdw==
|
||||
dependencies:
|
||||
is-core-module "^2.9.0"
|
||||
is-core-module "^2.12.0"
|
||||
path-parse "^1.0.7"
|
||||
supports-preserve-symlinks-flag "^1.0.0"
|
||||
|
||||
@ -5893,9 +5894,9 @@ rimraf@^3.0.2:
|
||||
glob "^7.1.3"
|
||||
|
||||
rimraf@^4.4.0:
|
||||
version "4.4.0"
|
||||
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-4.4.0.tgz#c7a9f45bb2ec058d2e60ef9aca5167974313d605"
|
||||
integrity sha512-X36S+qpCUR0HjXlkDe4NAOhS//aHH0Z+h8Ckf2auGJk3PTnx5rLmrHkwNdbVQuCSUhOyFrlRvFEllZOYE+yZGQ==
|
||||
version "4.4.1"
|
||||
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-4.4.1.tgz#bd33364f67021c5b79e93d7f4fa0568c7c21b755"
|
||||
integrity sha512-Gk8NlF062+T9CqNGn6h4tls3k6T1+/nXdOcSZVikNVtlRdYpA7wRJJMoXmuvOnLW844rPjdQ7JgXCYM6PPC/og==
|
||||
dependencies:
|
||||
glob "^9.2.0"
|
||||
|
||||
@ -5995,9 +5996,9 @@ semver@^6.0.0:
|
||||
integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==
|
||||
|
||||
semver@^7.3.4, semver@^7.3.7:
|
||||
version "7.3.8"
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.8.tgz#07a78feafb3f7b32347d725e33de7e2a2df67798"
|
||||
integrity sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==
|
||||
version "7.4.0"
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-7.4.0.tgz#8481c92feffc531ab1e012a8ffc15bdd3a0f4318"
|
||||
integrity sha512-RgOxM8Mw+7Zus0+zcLEUn8+JfoLpj/huFTItQy2hsM4khuC1HYRDp0cU482Ewn/Fcy6bCjufD8vAj7voC66KQw==
|
||||
dependencies:
|
||||
lru-cache "^6.0.0"
|
||||
|
||||
@ -6582,9 +6583,9 @@ trim-newlines@^3.0.0:
|
||||
integrity sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==
|
||||
|
||||
ts-command-line-args@^2.2.0:
|
||||
version "2.4.2"
|
||||
resolved "https://registry.yarnpkg.com/ts-command-line-args/-/ts-command-line-args-2.4.2.tgz#b4815b23c35f8a0159d4e69e01012d95690bc448"
|
||||
integrity sha512-mJLQQBOdyD4XI/ZWQY44PIdYde47JhV2xl380O7twPkTQ+Y5vFDHsk8LOeXKuz7dVY5aDCfAzRarNfSqtKOkQQ==
|
||||
version "2.5.0"
|
||||
resolved "https://registry.yarnpkg.com/ts-command-line-args/-/ts-command-line-args-2.5.0.tgz#7eeed3a6937b2612ea08a0794cf9d43fbbea89c4"
|
||||
integrity sha512-Ff7Xt04WWCjj/cmPO9eWTJX3qpBZWuPWyQYG1vnxJao+alWWYjwJBc5aYz3h5p5dE08A6AnpkgiCtP/0KXXBYw==
|
||||
dependencies:
|
||||
"@morgan-stanley/ts-mocking-bird" "^0.6.2"
|
||||
chalk "^4.1.0"
|
||||
@ -6622,9 +6623,9 @@ ts-node@^10.9.1:
|
||||
yn "3.1.1"
|
||||
|
||||
tsc-alias@^1.2.11:
|
||||
version "1.8.3"
|
||||
resolved "https://registry.yarnpkg.com/tsc-alias/-/tsc-alias-1.8.3.tgz#fe0c8331edd69b94160b2b936752b114f8063cb5"
|
||||
integrity sha512-/9JARcmXBrEqSuLjdSOqxY7/xI/AnvmBi4CU9/Ba2oX6Oq8vnd0OGSQTk+PIwqWJ5ZxskV0X/x15yzxCNTHU+g==
|
||||
version "1.8.5"
|
||||
resolved "https://registry.yarnpkg.com/tsc-alias/-/tsc-alias-1.8.5.tgz#6b74e938230573354c9118deb58fd341d06d6253"
|
||||
integrity sha512-Y3ka0olwSRdbHPyX5kXhYY2aoBKuT53DFdeY+PpQUR4hg5M/b8eIRmC8dL4FBdd0wT366iWc6iDUUGe6QwI7mg==
|
||||
dependencies:
|
||||
chokidar "^3.5.3"
|
||||
commander "^9.0.0"
|
||||
@ -6634,9 +6635,9 @@ tsc-alias@^1.2.11:
|
||||
plimit-lit "^1.2.6"
|
||||
|
||||
tsconfig-paths@^4.1.2:
|
||||
version "4.1.2"
|
||||
resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-4.1.2.tgz#4819f861eef82e6da52fb4af1e8c930a39ed979a"
|
||||
integrity sha512-uhxiMgnXQp1IR622dUXI+9Ehnws7i/y6xvpZB9IbUVOPy0muvdvgXeZOn88UcGPiT98Vp3rJPTa8bFoalZ3Qhw==
|
||||
version "4.2.0"
|
||||
resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz#ef78e19039133446d244beac0fd6a1632e2d107c"
|
||||
integrity sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==
|
||||
dependencies:
|
||||
json5 "^2.2.2"
|
||||
minimist "^1.2.6"
|
||||
@ -6746,10 +6747,10 @@ typedarray-to-buffer@^3.1.5:
|
||||
dependencies:
|
||||
is-typedarray "^1.0.0"
|
||||
|
||||
typescript@^5.1.0-dev.20230310:
|
||||
version "5.1.0-dev.20230316"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.1.0-dev.20230316.tgz#d57f1bde040419beaacf92ecb8adc5e29ecabdd5"
|
||||
integrity sha512-XQP4u67mBfrcRRfdyT3yvOAlCYlC0fERQOt9wwinZVALcj0BNO+7d7U1SVxzbb6RhXGEQ+xUgSIXxKXuHBZ0xw==
|
||||
typescript@^5:
|
||||
version "5.0.4"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.0.4.tgz#b217fd20119bd61a94d4011274e0ab369058da3b"
|
||||
integrity sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==
|
||||
|
||||
typical@^4.0.0:
|
||||
version "4.0.0"
|
||||
@ -7318,6 +7319,11 @@ ws@7.4.6:
|
||||
resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c"
|
||||
integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==
|
||||
|
||||
ws@8.2.3:
|
||||
version "8.2.3"
|
||||
resolved "https://registry.yarnpkg.com/ws/-/ws-8.2.3.tgz#63a56456db1b04367d0b721a0b80cae6d8becbba"
|
||||
integrity sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==
|
||||
|
||||
ws@^3.0.0:
|
||||
version "3.3.3"
|
||||
resolved "https://registry.yarnpkg.com/ws/-/ws-3.3.3.tgz#f1cf84fe2d5e901ebce94efaece785f187a228f2"
|
||||
|
Loading…
Reference in New Issue
Block a user