0.0.11-alpha: more sensible naming
Signed-off-by: T-Hax <>
This commit is contained in:
parent
d1d23f252a
commit
cd64bc0f63
@ -6,7 +6,7 @@ import { TornadoInstance, TornadoProxy } from './deth'
|
||||
|
||||
// Monorepo
|
||||
import { RelayerProperties as RelayerDataProperties } from '@tornado/sdk-data'
|
||||
import { ZKDepositData, InputFor } from '@tornado/sdk-crypto'
|
||||
import { DepositInfo, InputFor } from '@tornado/sdk-crypto'
|
||||
|
||||
// External imports
|
||||
import { TransactionRequest } from '@ethersproject/abstract-provider'
|
||||
@ -174,58 +174,59 @@ export class Core extends Synchronizer {
|
||||
return Contracts.getProxy(String(this.chain.id), this.chain.provider)
|
||||
}
|
||||
|
||||
async buildDepositProof(
|
||||
async createDepositProof(
|
||||
instance: TornadoInstance,
|
||||
relayerProperties: RelayerProperties,
|
||||
recipientAddress: string,
|
||||
zkDepositsData: ZKDepositData,
|
||||
depositInfo: DepositInfo,
|
||||
options?: Options.Core.BuildDepositProof
|
||||
): Promise<Array<string>> {
|
||||
return (
|
||||
await this.buildDepositProofs(
|
||||
await this.createDepositProofs(
|
||||
instance,
|
||||
relayerProperties,
|
||||
[recipientAddress],
|
||||
[zkDepositsData],
|
||||
[depositInfo],
|
||||
options
|
||||
)
|
||||
)[0]
|
||||
}
|
||||
|
||||
// TODO: Abstract out verification parts of this and provide it as a standalone service in crypto or somewhere else
|
||||
/**
|
||||
* @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. 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 depositInfo 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 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(
|
||||
async createDepositProofs(
|
||||
instance: TornadoInstance,
|
||||
relayerProperties: RelayerProperties,
|
||||
recipientAddresses: Array<string>,
|
||||
zkDepositsData: Array<ZKDepositData>,
|
||||
depositInfo: Array<DepositInfo>,
|
||||
options?: Options.Core.BuildDepositProof
|
||||
): Promise<Array<Array<string>>> {
|
||||
this._checkProvider('buildDepositProofs')
|
||||
this._checkProvider('createDepositProofs')
|
||||
|
||||
// Extract commitments and nullifier hashes
|
||||
const hexCommitments: string[] = []
|
||||
const hexNullifierHashes: string[] = []
|
||||
const purchaseAmounts =
|
||||
options?.ethPurchaseAmounts ?? new Array(zkDepositsData.length).fill(BigNumber.from(0))
|
||||
options?.ethPurchaseAmounts ?? new Array(depositInfo.length).fill(BigNumber.from(0))
|
||||
|
||||
if (zkDepositsData.length !== recipientAddresses.length)
|
||||
if (depositInfo.length !== recipientAddresses.length)
|
||||
throw ErrorUtils.getError(
|
||||
'Core.buildDepositProofs: the number of recipients must equal the length of zkDepositsData.'
|
||||
'Core.createDepositProofs: the number of recipients must equal the length of depositInfo.'
|
||||
)
|
||||
|
||||
if (zkDepositsData.length !== purchaseAmounts.length)
|
||||
if (depositInfo.length !== purchaseAmounts.length)
|
||||
throw ErrorUtils.getError(
|
||||
'Core.buildDepositProofs: if purchase amounts is specified, it must equal the length of zkDepositsData.'
|
||||
'Core.createDepositProofs: if purchase amounts is specified, it must equal the length of depositInfo.'
|
||||
)
|
||||
|
||||
zkDepositsData.forEach((deposit) => {
|
||||
depositInfo.forEach((deposit) => {
|
||||
hexCommitments.push(deposit.hexCommitment)
|
||||
hexNullifierHashes.push(deposit.hexNullifierHash)
|
||||
})
|
||||
@ -258,7 +259,7 @@ export class Core extends Synchronizer {
|
||||
// Also add the invalid commitments. We can do leafIndices[i] because the matched one are concatenated
|
||||
// at the start
|
||||
|
||||
for (let i = 0, len = zkDepositsData.length; i < len; i++) {
|
||||
for (let i = 0, len = depositInfo.length; i < len; i++) {
|
||||
if (!leafIndices[i]) invalidCommitments.push(hexCommitments[i])
|
||||
if (checkSpent && checkSpentArray![i]) spentNotes.push(hexNullifierHashes[i])
|
||||
}
|
||||
@ -269,7 +270,7 @@ export class Core extends Synchronizer {
|
||||
|
||||
if (commitmentsAreInvalid || notesAreSpent)
|
||||
throw ErrorUtils.getError(
|
||||
`Core.buildDepositProofs: ` +
|
||||
`Core.createDepositProofs: ` +
|
||||
(commitmentsAreInvalid
|
||||
? `following commitments are invalid:\n\n${invalidCommitments.join('\n')}\n\n`
|
||||
: '') +
|
||||
@ -294,7 +295,7 @@ export class Core extends Synchronizer {
|
||||
// Check whether the root is valid
|
||||
if (checkKnownRoot && !(await instance.isKnownRoot(root)))
|
||||
throw ErrorUtils.getError(
|
||||
'Core.buildDepositProofs: the merkle tree created is not valid, something went wrong with syncing.'
|
||||
'Core.createDepositProofs: the merkle tree created is not valid, something went wrong with syncing.'
|
||||
)
|
||||
|
||||
// Rest of note invariant arguments
|
||||
@ -319,7 +320,7 @@ export class Core extends Synchronizer {
|
||||
|
||||
if (!tokenPrice && !native)
|
||||
throw ErrorUtils.getError(
|
||||
'Core.buildDepositProofs: a token price MUST be supplied if the token withdrawn is not native.'
|
||||
'Core.createDepositProofs: a token price MUST be supplied if the token withdrawn is not native.'
|
||||
)
|
||||
|
||||
this.emit(
|
||||
@ -335,13 +336,13 @@ export class Core extends Synchronizer {
|
||||
)
|
||||
|
||||
// Compute proofs
|
||||
for (let i = 0, len = zkDepositsData.length; i < len; i++) {
|
||||
for (let i = 0, len = depositInfo.length; i < len; i++) {
|
||||
inputsForProofs.push({
|
||||
public: {
|
||||
root: root,
|
||||
tree: merkleTree,
|
||||
leafIndex: leafIndices[i],
|
||||
hexNullifierHash: zkDepositsData[i].hexNullifierHash,
|
||||
hexNullifierHash: depositInfo[i].hexNullifierHash,
|
||||
recipientAddress: recipientAddresses[i],
|
||||
relayerAddress: relayerProperties.address,
|
||||
fee: this._calcWithdrawalFee(
|
||||
@ -358,8 +359,8 @@ export class Core extends Synchronizer {
|
||||
refund: purchaseAmounts[i] ? bigInt(purchaseAmounts[i].toString()) : bigInt(0)
|
||||
},
|
||||
private: {
|
||||
nullifier: zkDepositsData[i].nullifier,
|
||||
secret: zkDepositsData[i].secret
|
||||
nullifier: depositInfo[i].nullifier,
|
||||
secret: depositInfo[i].secret
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -447,7 +448,7 @@ export class Core extends Synchronizer {
|
||||
async loadNotes(
|
||||
indexes?: Array<number>,
|
||||
keys?: Partial<Keys.InstanceLookup>
|
||||
): Promise<Array<ZKDepositData>> {
|
||||
): Promise<Array<DepositInfo>> {
|
||||
const rows = await Cache.loadContents<Docs.Note>('DepositNotes')
|
||||
|
||||
let docs: Array<Docs.Note | undefined> = []
|
||||
@ -472,11 +473,11 @@ export class Core extends Synchronizer {
|
||||
return this.parseNotes(notes)
|
||||
}
|
||||
|
||||
parseNotes(notes: Array<string>): Array<ZKDepositData> {
|
||||
parseNotes(notes: Array<string>): Array<DepositInfo> {
|
||||
return notes.map((note) => Primitives.parseNote(note))
|
||||
}
|
||||
|
||||
parseNote(note: string): ZKDepositData {
|
||||
parseNote(note: string): DepositInfo {
|
||||
return this.parseNotes([note])[0]
|
||||
}
|
||||
|
||||
@ -573,10 +574,10 @@ export class Core extends Synchronizer {
|
||||
* @param options Whether or not to populate the transactions (only in the sense of encoding transaction data), and whether to backup notes and invoices. Defaults: `depositsPerInstance = [1], doNotPopulate = false, backup { notes = true, invoices = false }` Deposits per instance are hardcoded to 1, since we're doing a single transaction.
|
||||
* @returns A promise which resolves to the created transaction.
|
||||
*/
|
||||
buildDepositTransaction(instance: TornadoInstance, options?: Options.Core.Deposit): Transactions.Deposit {
|
||||
createDepositTransaction(instance: TornadoInstance, options?: Options.Core.Deposit): Transactions.Deposit {
|
||||
let opts: Options.Core.Deposit = options ?? {}
|
||||
opts.depositsPerInstance = [1]
|
||||
return this.buildDepositTransactions([instance], opts)[0]
|
||||
return this.createDepositTransactions([instance], opts)[0]
|
||||
}
|
||||
|
||||
/**
|
||||
@ -586,11 +587,11 @@ export class Core extends Synchronizer {
|
||||
* @returns A promise which resolves to the created transactions.
|
||||
* @todo TODO: Maybe this should be sync and deposit backups should be async somewhere else
|
||||
*/
|
||||
buildDepositTransactions(
|
||||
createDepositTransactions(
|
||||
instances: Array<TornadoInstance>,
|
||||
options?: Options.Core.Deposit
|
||||
): Array<Transactions.Deposit> {
|
||||
this._checkProvider('buildDepositTransactions')
|
||||
this._checkProvider('createDepositTransactions')
|
||||
|
||||
const depositsPerInstance = options?.depositsPerInstance ?? new Array<number>(instances.length).fill(1)
|
||||
|
||||
@ -598,7 +599,7 @@ export class Core extends Synchronizer {
|
||||
|
||||
if (depositsPerInstance.length != instances.length)
|
||||
throw ErrorUtils.getError(
|
||||
'Core.buildDepositTx: number of deposit amount elements must equal the number of instances!'
|
||||
'Core.createDepositTx: number of deposit amount elements must equal the number of instances!'
|
||||
)
|
||||
|
||||
const chainId = this.chain.id
|
||||
|
@ -132,7 +132,7 @@ export namespace InputFor {
|
||||
*/
|
||||
type __InputAliasDelimiter = null
|
||||
|
||||
export type ZKDepositData = OutputOf.CreateDeposit
|
||||
export type DepositInfo = OutputOf.CreateDeposit
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ SETUP ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
/**
|
||||
@ -174,7 +174,7 @@ export namespace Primitives {
|
||||
return HexUtils.bufferToHex(msg, 62)
|
||||
}
|
||||
|
||||
export function parseNote(hexNote: string): ZKDepositData {
|
||||
export function parseNote(hexNote: string): DepositInfo {
|
||||
const _hexNote = hexNote.split('_')[1] ?? hexNote
|
||||
const buffer = Buffer.from(_hexNote.slice(2), 'hex')
|
||||
return createDeposit({
|
||||
@ -190,7 +190,7 @@ export namespace Primitives {
|
||||
nullifier: NumberUtils.randomBigInteger(31),
|
||||
secret: NumberUtils.randomBigInteger(31)
|
||||
}
|
||||
): ZKDepositData {
|
||||
): DepositInfo {
|
||||
// @ts-expect-error
|
||||
let preimage = Buffer.concat([input.nullifier.leInt2Buff(31), input.secret.leInt2Buff(31)])
|
||||
let commitment = calcPedersenHash({ msg: preimage })
|
||||
|
@ -64,7 +64,7 @@ export interface RelayerProperties {
|
||||
export namespace Options {
|
||||
export interface Cache {
|
||||
adapter?: string
|
||||
cachePath?: string
|
||||
cacheDirPath?: string
|
||||
persistent?: boolean
|
||||
}
|
||||
}
|
||||
@ -129,13 +129,13 @@ export namespace Files {
|
||||
}
|
||||
}
|
||||
|
||||
export async function wipeCache(prompt: boolean = true, cachePath?: string): Promise<void> {
|
||||
const dir = await opendir(getCachePath('', cachePath))
|
||||
export async function wipeCache(prompt: boolean = true, cacheDirPath?: string): Promise<void> {
|
||||
const dir = await opendir(getCachePath('', cacheDirPath))
|
||||
const toRemove: string[] = []
|
||||
const userInput = createInterface({ input: process.stdin, output: process.stdout })
|
||||
for await (const entry of dir) {
|
||||
if (entry.name.match('(Deposit.*)|(Withdrawal.*)|(Note.*)|(Invoice.*)'))
|
||||
toRemove.push(getCachePath(entry.name, cachePath))
|
||||
toRemove.push(getCachePath(entry.name, cacheDirPath))
|
||||
}
|
||||
if (toRemove.length != 0) {
|
||||
if (prompt) {
|
||||
@ -643,13 +643,15 @@ export namespace Cache {
|
||||
private _path: string
|
||||
|
||||
name: string
|
||||
isOpen: boolean
|
||||
|
||||
db: PouchDB.Database<T>
|
||||
|
||||
private _unzip(cachePath?: string): void {
|
||||
private _unzip(cacheDirPath?: string): void {
|
||||
if (existsSync(this._path + '.tar.gz')) {
|
||||
if (existsSync(this._path)) {
|
||||
throw ErrorUtils.getError(`Can't load both ${this.name} and ${this.name + '.tar.gz'}, remove one!`)
|
||||
} else Files.gunzipSync(this._path, Files.getCachePath('', cachePath))
|
||||
} else Files.gunzipSync(this._path, Files.getCachePath('', cacheDirPath))
|
||||
}
|
||||
}
|
||||
|
||||
@ -664,18 +666,20 @@ export namespace Cache {
|
||||
|
||||
const dbAdapter = options?.adapter ?? (options?.persistent === false ? 'memory' : 'leveldb')
|
||||
|
||||
if (options?.cachePath)
|
||||
if (options.cachePath.charAt(options.cachePath.length - 1) != '/') options.cachePath += '/'
|
||||
if (options?.cacheDirPath)
|
||||
if (options.cacheDirPath.charAt(options.cacheDirPath.length - 1) != '/') options.cacheDirPath += '/'
|
||||
|
||||
if (!Files.cacheDirExists(options?.cachePath)) Files.makeCacheDir()
|
||||
if (!Files.cacheDirExists(options?.cacheDirPath)) Files.makeCacheDir()
|
||||
|
||||
this._path = Files.getCachePath(name, options?.cachePath)
|
||||
this._path = Files.getCachePath(name, options?.cacheDirPath)
|
||||
|
||||
this._adapter = dbAdapter
|
||||
|
||||
this._unzip(options?.cachePath)
|
||||
this._unzip(options?.cacheDirPath)
|
||||
|
||||
this.db = new PouchDB<T>(this._path, { adapter: dbAdapter })
|
||||
|
||||
this.isOpen = true
|
||||
}
|
||||
|
||||
async zip(outDirPath?: string, close: boolean = false): Promise<void> {
|
||||
@ -686,6 +690,8 @@ export namespace Cache {
|
||||
Files.gzipSync(this._path, (outDirPath ?? Files.parentPath(this._path)) + this.name)
|
||||
|
||||
if (!close) this.db = new PouchDB<T>(this._path, { adapter: this._adapter })
|
||||
|
||||
this.isOpen = !close
|
||||
}
|
||||
|
||||
async get(keys: Array<any>): Promise<T> {
|
||||
@ -752,6 +758,7 @@ export namespace Cache {
|
||||
}
|
||||
}>
|
||||
|
||||
// TODO: This logic needs improvement
|
||||
export async function loadContents<T extends Docs.Base>(
|
||||
nameOfContent: string,
|
||||
full: boolean = true,
|
||||
|
@ -14,7 +14,7 @@ async function main() {
|
||||
await core.connect(new providers.JsonRpcProvider("https://some.rpc.url"))
|
||||
|
||||
// Build tx (synchronous)
|
||||
const tx = core.buildDepositTransaction(core.getInstance("usdc", "100"))
|
||||
const tx = core.createDepositTransaction(core.getInstance("usdc", "100"))
|
||||
|
||||
// Print the tx to console
|
||||
console.log(tx)
|
||||
@ -69,7 +69,7 @@ async function main() {
|
||||
}))[0]
|
||||
|
||||
// Now build the proof
|
||||
const proof = await core.buildDepositProof(instance, relayer.properties, receiverAddress, note, {
|
||||
const proof = await core.createDepositProof(instance, relayer.properties, receiverAddress, note, {
|
||||
// Defaults after the function populates as a showcase
|
||||
// You can also leave all of this out and it will set it by itself
|
||||
checkNotesSpent: true,
|
||||
|
@ -215,11 +215,11 @@ describe('Core', () => {
|
||||
dai = dai.connect(daiWhaleSigner)
|
||||
})
|
||||
|
||||
it('buildDepositTransaction: build a single eth deposit tx and succeed', async () => {
|
||||
it('createDepositTransaction: build a single eth deposit tx and succeed', async () => {
|
||||
const initBal = await needsMoney.getBalance()
|
||||
|
||||
// Build tx and load cache for this test
|
||||
const tx = core.buildDepositTransaction(smallestEth)
|
||||
const tx = core.createDepositTransaction(smallestEth)
|
||||
|
||||
// Listen to deposit events
|
||||
core.listenForDeposits(smallestEth)
|
||||
@ -246,14 +246,14 @@ describe('Core', () => {
|
||||
expect(endBal).to.be.lte(parseUnits('999.9'))
|
||||
}).timeout(0)
|
||||
|
||||
it('buildDepositProof: it should be able to build an eth proof', async () => {
|
||||
it('createDepositProof: it should be able to build an eth proof', async () => {
|
||||
// Get all of the notes
|
||||
const notes = await core.loadNotes()
|
||||
|
||||
// Build proof
|
||||
let proof: any
|
||||
|
||||
proof = await core.buildDepositProof(
|
||||
proof = await core.createDepositProof(
|
||||
smallestEth,
|
||||
{
|
||||
address: withdrawerAddress
|
||||
@ -279,7 +279,7 @@ describe('Core', () => {
|
||||
).to.changeEtherBalance(needsMoney, ethDelta)
|
||||
}).timeout(0)
|
||||
|
||||
it('buildDepositTransaction: build a single token deposit tx and succeed', async () => {
|
||||
it('createDepositTransaction: build a single token deposit tx and succeed', async () => {
|
||||
// Prep deposit amount, proxy for approval, cache, bal for comp
|
||||
const depositAmount = parseUnits('100000')
|
||||
const proxy = core.getProxy()
|
||||
@ -296,7 +296,7 @@ describe('Core', () => {
|
||||
|
||||
dai = dai.connect(needsMoney)
|
||||
|
||||
const tx = core.buildDepositTransaction(dai100K)
|
||||
const tx = core.createDepositTransaction(dai100K)
|
||||
|
||||
// Approve dai for the proxy first (transferFrom)
|
||||
await dai.approve(proxy.address, depositAmount)
|
||||
@ -322,7 +322,7 @@ describe('Core', () => {
|
||||
expect(await dai.balanceOf(needsMoneyAddress)).to.equal(0)
|
||||
}).timeout(0)
|
||||
|
||||
it('buildDepositProof: it should be able to build a token proof', async () => {
|
||||
it('createDepositProof: it should be able to build a token proof', async () => {
|
||||
if (!process.env.TEST_RELAYER_DOMAIN) throw ErrorUtils.getError('core.test.ts: Need a relayer name')
|
||||
|
||||
// Get all of the notes
|
||||
@ -344,7 +344,7 @@ describe('Core', () => {
|
||||
properties.prices.set('dai', BigNumber.from(10).pow(18).div(1800))
|
||||
|
||||
// Build proof with relayer properties this time
|
||||
const proof = await core.buildDepositProof(dai100K, properties, needsMoneyAddress, note, {
|
||||
const proof = await core.createDepositProof(dai100K, properties, needsMoneyAddress, note, {
|
||||
// On by default but stating for visibility
|
||||
checkNotesSpent: true,
|
||||
checkKnownRoot: true
|
||||
@ -360,7 +360,7 @@ describe('Core', () => {
|
||||
).to.changeTokenBalance(dai, needsMoney, daiDelta)
|
||||
}).timeout(0)
|
||||
|
||||
it.only('buildDepositTransactions: multiple eth deposits', async () => {
|
||||
it.only('createDepositTransactions: multiple eth deposits', async () => {
|
||||
const instances = core.getInstances(
|
||||
[0.1, 1, 10, 100].map((el) => {
|
||||
return { token: 'eth', denomination: el }
|
||||
@ -372,7 +372,7 @@ describe('Core', () => {
|
||||
|
||||
const depositsPer = [1, 1, 2, 1]
|
||||
|
||||
const txs = core.buildDepositTransactions(instances, {
|
||||
const txs = core.createDepositTransactions(instances, {
|
||||
depositsPerInstance: depositsPer
|
||||
})
|
||||
|
||||
@ -398,7 +398,7 @@ describe('Core', () => {
|
||||
expect(await needsMoney.getBalance()).to.be.lte(parseUnits('888.8'))
|
||||
}).timeout(0)
|
||||
|
||||
it.only('buildDepositProofs: should be able to withdraw', async () => {
|
||||
it.only('createDepositProofs: should be able to withdraw', async () => {
|
||||
// ETH instances
|
||||
const instances = core.getInstances(
|
||||
[0.1, 1, 10, 100].map((el) => {
|
||||
@ -414,7 +414,7 @@ describe('Core', () => {
|
||||
|
||||
// Handle all withdrawals
|
||||
for (let i = 0, len = instances.length; i < len; i++) {
|
||||
const proofs = await core.buildDepositProofs(
|
||||
const proofs = await core.createDepositProofs(
|
||||
instances[i],
|
||||
{
|
||||
address: withdrawerAddress
|
||||
@ -448,7 +448,7 @@ describe('Core', () => {
|
||||
}
|
||||
}).timeout(0)
|
||||
|
||||
it('buildDepositTransactions: multiple token deposits', async () => {
|
||||
it('createDepositTransactions: multiple token deposits', async () => {
|
||||
// Prepare contracts
|
||||
const denoms = [100, 1000, 10000, 100000]
|
||||
const proxy = core.getProxy()
|
||||
@ -475,7 +475,7 @@ describe('Core', () => {
|
||||
|
||||
// Build txs
|
||||
|
||||
const txs = core.buildDepositTransactions(instances, {
|
||||
const txs = core.createDepositTransactions(instances, {
|
||||
depositsPerInstance: depositsPer
|
||||
})
|
||||
|
||||
@ -513,7 +513,7 @@ describe('Core', () => {
|
||||
expect(await dai.balanceOf(needsMoneyAddress)).to.equal(0)
|
||||
}).timeout(0)
|
||||
|
||||
it('buildDepositProofs: multiple dai withdrawals', async () => {
|
||||
it('createDepositProofs: multiple dai withdrawals', async () => {
|
||||
// ETH instances
|
||||
const denoms = [100, 1000, 10000, 100000]
|
||||
const instances = core.getInstances(
|
||||
@ -544,7 +544,7 @@ describe('Core', () => {
|
||||
|
||||
// Handle all withdrawals
|
||||
for (let i = 0, len = instances.length; i < len; i++) {
|
||||
const proofs = await core.buildDepositProofs(
|
||||
const proofs = await core.createDepositProofs(
|
||||
instances[i],
|
||||
properties,
|
||||
new Array(depositsPer[i]).fill(needsMoneyAddress),
|
||||
|
Loading…
Reference in New Issue
Block a user