0.0.10-alpha

Signed-off-by: T-Hax <>
This commit is contained in:
T-Hax 2023-05-11 19:41:44 +00:00
parent 798598cfff
commit 35ea8d2d14
15 changed files with 157 additions and 113 deletions

8
.yarn/versions/6944eba2.yml vendored Normal file

@ -0,0 +1,8 @@
undecided:
- "@tornado/sdk-monorepo"
- "@tornado/sdk-chain"
- "@tornado/sdk-core"
- "@tornado/sdk-crypto"
- "@tornado/sdk-data"
- "@tornado/sdk-utils"
- "@tornado/sdk-web"

@ -13,7 +13,7 @@
"crypto", "crypto",
"zk" "zk"
], ],
"version": "0.0.8-alpha", "version": "0.0.9-alpha",
"engines": { "engines": {
"node": "^18" "node": "^18"
}, },
@ -80,5 +80,6 @@
"tsconfig-paths@4.2.0": { "tsconfig-paths@4.2.0": {
"unplugged": true "unplugged": true
} }
} },
"stableVersion": "0.0.8-alpha"
} }

@ -13,7 +13,7 @@
"crypto", "crypto",
"zk" "zk"
], ],
"version": "0.0.8-alpha", "version": "0.0.10-alpha",
"engines": { "engines": {
"node": "^18" "node": "^18"
}, },
@ -83,5 +83,6 @@
"tsconfig-paths@4.2.0": { "tsconfig-paths@4.2.0": {
"unplugged": true "unplugged": true
} }
} },
"stableVersion": "0.0.8-alpha"
} }

@ -147,11 +147,8 @@ export class Core extends Synchronizer {
} }
private _checkProvider(parentCallName: string): void { private _checkProvider(parentCallName: string): void {
try { if (!this._chain)
this._chain?.id
} catch (err) {
throw ErrorUtils.getError('Core.' + parentCallName + ': you must first connect a provider!') throw ErrorUtils.getError('Core.' + parentCallName + ': you must first connect a provider!')
}
} }
async connect(provider: Provider): Promise<void> { async connect(provider: Provider): Promise<void> {
@ -161,12 +158,14 @@ export class Core extends Synchronizer {
} }
getInstances(keys: Array<{ token: string; denomination: number | string }>): Array<TornadoInstance> { getInstances(keys: Array<{ token: string; denomination: number | string }>): Array<TornadoInstance> {
this._checkProvider('getInstances')
return keys.map((key) => return keys.map((key) =>
Contracts.getInstance(String(this.chain.id), key.token, String(key.denomination), this.chain.provider) Contracts.getInstance(String(this.chain.id), key.token, String(key.denomination), this.chain.provider)
) )
} }
getInstance(token: string, denomination: number | string): TornadoInstance { getInstance(token: string, denomination: number | string): TornadoInstance {
this._checkProvider('getInstance')
return this.loadInstance(this.chain.id, token, denomination) return this.loadInstance(this.chain.id, token, denomination)
} }
@ -591,6 +590,8 @@ export class Core extends Synchronizer {
instances: Array<TornadoInstance>, instances: Array<TornadoInstance>,
options?: Options.Core.Deposit options?: Options.Core.Deposit
): Array<Transactions.Deposit> { ): Array<Transactions.Deposit> {
this._checkProvider('buildDepositTransactions')
const depositsPerInstance = options?.depositsPerInstance ?? new Array<number>(instances.length).fill(1) const depositsPerInstance = options?.depositsPerInstance ?? new Array<number>(instances.length).fill(1)
const doNotPopulate = options?.doNotPopulate ?? false const doNotPopulate = options?.doNotPopulate ?? false

@ -13,7 +13,7 @@
"crypto", "crypto",
"zk" "zk"
], ],
"version": "0.0.8-alpha", "version": "0.0.9-alpha",
"engines": { "engines": {
"node": "^18" "node": "^18"
}, },
@ -75,5 +75,6 @@
"tsconfig-paths@4.2.0": { "tsconfig-paths@4.2.0": {
"unplugged": true "unplugged": true
} }
} },
"stableVersion": "0.0.8-alpha"
} }

@ -13,7 +13,7 @@
"crypto", "crypto",
"zk" "zk"
], ],
"version": "0.0.8-alpha", "version": "0.0.9-alpha",
"engines": { "engines": {
"node": "^18" "node": "^18"
}, },
@ -79,5 +79,6 @@
"tsconfig-paths@4.2.0": { "tsconfig-paths@4.2.0": {
"unplugged": true "unplugged": true
} }
} },
"stableVersion": "0.0.8-alpha"
} }

@ -13,7 +13,7 @@
"crypto", "crypto",
"zk" "zk"
], ],
"version": "0.0.8-alpha", "version": "0.0.9-alpha",
"engines": { "engines": {
"node": "^18" "node": "^18"
}, },
@ -68,5 +68,6 @@
"tsconfig-paths@4.2.0": { "tsconfig-paths@4.2.0": {
"unplugged": true "unplugged": true
} }
} },
"stableVersion": "0.0.8-alpha"
} }

@ -13,7 +13,7 @@
"crypto", "crypto",
"zk" "zk"
], ],
"version": "0.0.8-alpha", "version": "0.0.9-alpha",
"engines": { "engines": {
"node": "^18" "node": "^18"
}, },
@ -76,5 +76,6 @@
"tsconfig-paths@4.2.0": { "tsconfig-paths@4.2.0": {
"unplugged": true "unplugged": true
} }
} },
"stableVersion": "0.0.8-alpha"
} }

@ -13,7 +13,7 @@
"crypto", "crypto",
"zk" "zk"
], ],
"version": "0.0.8-alpha", "version": "0.0.10-alpha",
"engines": { "engines": {
"node": "^18" "node": "^18"
}, },
@ -61,5 +61,6 @@
"tsconfig-paths@4.2.0": { "tsconfig-paths@4.2.0": {
"unplugged": true "unplugged": true
} }
} },
"stableVersion": "0.0.8-alpha"
} }

@ -2,7 +2,9 @@
SDK to integrate your protocol with Tornado Cash. SDK to integrate your protocol with Tornado Cash.
[Check out the docs here.](./docs/ABOUT.md) [Please check out the docs here.](./docs/ABOUT.md)
You SHOULD familiarize yourself with features [still considered experimental](./docs/EXPERIMENTAL.md).
You may also read, [a note on testing.](./docs/TESTS.md) You may also read, [a note on testing.](./docs/TESTS.md)

@ -1,7 +1,8 @@
# Tornado Cash SDK # Tornado Cash SDK
A collection of Typescript packages which enable you to easily use the Tornado Cash protocol. A collection of Typescript packages which enable you to easily use the Tornado Cash protocol. Please note that you should familiarize yourself with any still experimental functions, this will be the first link below.
* [Experimental features](./EXPERIMENTAL.md)
* [Installation](./INSTALLATION.md) * [Installation](./INSTALLATION.md)
* [Usage](./USAGE.md) * [Usage](./USAGE.md)

9
docs/EXPERIMENTAL.md Normal file

@ -0,0 +1,9 @@
# Functions which are still considered experimental
Ranked by danger.
* **Core.buildDepositProof(s)** ➡️ because we still need more testnet tests. Nominally, should work though. Use at own risk. Very very likely won't break.
* **Relayer.handleWithdrawal** ➡️ because no test relayer has been yet available to handle this. Will likely break.
* **Core.loadNotes** ➡️ more tests are needed on filtering behaviour. Likely won't break.

@ -4,12 +4,16 @@
```ts ```ts
import * as Tornado from "@tornado/sdk" import * as Tornado from "@tornado/sdk"
import { providers } from "ethers"
async function main() { async function main() {
// Get the core Tornado Cash logic. // Get the core Tornado Cash logic.
const core = new Tornado.Core() const core = new Tornado.Core()
// Build tx // Connect a provider
await core.connect(new providers.JsonRpcProvider("https://some.rpc.url"))
// Build tx (synchronous)
const tx = core.buildDepositTransaction(core.getInstance("usdc", "100")) const tx = core.buildDepositTransaction(core.getInstance("usdc", "100"))
// Print the tx to console // Print the tx to console
@ -21,59 +25,63 @@ main()
### Build a withdrawal transaction ### Build a withdrawal transaction
This is _still_ considered experimental, I will flag it as _not experimental_ after a certain number of production tests.
```ts ```ts
import * as Tornado from "@tornado/sdk" import * as Tornado from "@tornado/sdk"
import { providers, BigNumber } from "ethers"
async function main() { async function main() {
// The address to receive the funds... // The address to receive the funds...
const receiverAddress = "0x0000000000000000000000000000000000000000" const receiverAddress = "0x0000000000000000000000000000000000000000"
// Get the core Tornado Cash logic. // Get the core Tornado Cash logic.
const core = new Tornado.Core() const core = new Tornado.Core()
// Get a regular ethers v5 provider. // Get a regular ethers v5 provider.
const provider = new providers.JsonRpcProvider("ENTER YOUR RPC URL HERE!") const provider = new providers.JsonRpcProvider("https://some.rpc.url")
// This time we need to connect the provider // This time we need to connect the provider
await core.connect(provider) await core.connect(provider)
// We also need a relayer // We also need a relayer
const relayer = new Tornado.Web.Relayer({ const relayer = new Tornado.Web.Relayer({
url: "https://" + "ENTER YOUR CHOSEN RELAYER DOMAIN HERE", url: "https://" + "some.relayer.org",
// Web can also instead provide a TorHttpClient or an (ethers v5) TorProvider // Web can also instead provide a TorHttpClient or an (ethers v5) TorProvider
httpClient: new Tornado.Web.RegularHttpClient() httpClient: new Tornado.Web.RegularHttpClient()
}) })
// We always have to fetch the current properties of a relayer // We always have to fetch the current properties of a relayer
await relayer.fetchProperties() await relayer.fetchProperties()
// Once that is done let's get an instance we have a proof of // Once that is done let's get an instance we have a proof of
const instance = core.getInstance("eth", "0.1") const instance = core.getInstance("eth", "0.1")
// We have to load the note, the arguments can be // We have to load the note, the arguments can be
// indexes - indexes according to which you may choose the notes in cache // indexes - indexes according to which you may choose the notes in cache
// keys - the keys according to which you may choose the notes in cache // keys - the keys according to which you may choose the notes in cache
// In our case we've set indexes to undefined and choosing our notes according to the instance // In our case we've set indexes to undefined and choosing our notes according to the instance
// And then selecting the first one of those // And then selecting the first one of those
const note = (await core.loadNotes(undefined, { const note = (await core.loadNotes(undefined, {
network: core.chain.id, network: '' + core.chain.id,
token: "eth", token: "eth",
denomination: "0.1" denomination: "0.1"
}))[0] }))[0]
// Now build the proof // Now build the proof
const proof = await core.buildDepositProof(instance, relayer.properties, receiverAddress, note, { const proof = await core.buildDepositProof(instance, relayer.properties, receiverAddress, note, {
// Defaults // Defaults after the function populates as a showcase
checkNotesSpent: true, // You can also leave all of this out and it will set it by itself
checkKnownRoot: true, checkNotesSpent: true,
merkleTreeHeight: 20, checkKnownRoot: true,
tokenDecimals: 18, merkleTreeHeight: 20,
ethPurchaseAmounts: [BigNumber.from(0)], tokenDecimals: 18,
gasPrice: undefined, ethPurchaseAmounts: [BigNumber.from(0)], // When doing multiple proofs, more elements in array
gasPriceCushion: undefined, gasPrice: undefined,
}) gasPriceCushion: undefined,
})
console.log(proof) console.log(proof)
} }
main() main()
@ -82,28 +90,30 @@ main()
### Synchronize Deposit Events Over Clearnet Without Sync Logs ### Synchronize Deposit Events Over Clearnet Without Sync Logs
```ts ```ts
import { providers } from "ethers"
import * as Tornado from "@tornado/sdk" import * as Tornado from "@tornado/sdk"
import { providers } from "ethers"
async function sync() { async function sync() {
// Get a regular ethers v5 provider. // Get a regular ethers v5 provider.
const provider = new providers.JsonRpcProvider("ENTER YOUR RPC URL HERE!") const provider = new providers.JsonRpcProvider("https://some.rpc.url")
// Get the core Tornado Cash logic. // Get the core Tornado Cash logic.
const core = new Tornado.Core() const core = new Tornado.Core()
// Connect the provider (necessary) // Connect the provider (necessary)
await core.connect(provider) await core.connect(provider)
// Get the instance to sync // Get the instance to sync
const instance = await core.getInstance("eth", 0.1) const instance = await core.getInstance("eth", 0.1)
// Sync! Output will be in the project dir in the cache folder // Sync! Output will be in the project dir in the cache folder
await core.syncDeposits(instance) await core.syncDeposits(instance)
// Now export it as an archive! // Now export it as an archive!
await core.exportAsArchive('Deposits1ETH0.1') await core.exportAsArchive('Deposits1ETH0.1')
} }
sync()
``` ```
### Synchronize Deposit Events Over Tor Without Sync Logs ### Synchronize Deposit Events Over Tor Without Sync Logs
@ -112,31 +122,31 @@ async function sync() {
import * as Tornado from "@tornado/sdk" import * as Tornado from "@tornado/sdk"
async function sync() { async function sync() {
// Get a torified ethers v5 provider. // Get a torified ethers v5 provider.
// You can set the port to 9150 if you use Tor Browser! // You can set the port to 9150 if you use Tor Browser!
const provider = new Tornado.Web.TorProvider("ENTER YOUR RPC URL HERE!", { port: 9050 }) const provider = new Tornado.Web.TorProvider("https://some.rpc.url", { port: 9050 })
// Get the core Tornado Cash logic. // Get the core Tornado Cash logic.
const core = new Tornado.Core() const core = new Tornado.Core()
// Connect the provider (necessary) // Connect the provider (necessary)
await core.connect(provider) await core.connect(provider)
// Get the instance to sync // Get the instance to sync
const instance = await core.getInstance("eth", 0.1) const instance = core.getInstance("eth", 0.1)
// Sync! // Sync!
await core.syncDeposits(instance, await core.syncDeposits(instance,
{ {
// In this example, we're forcing to sync from the start block such that // In this example, we're forcing to sync from the start block such that
// if some RPC doesn't index all events, that we can rerun and insert other // if some RPC doesn't index all events, that we can rerun and insert other
// elements not found in the former. PouchDB handles the insertions. // elements not found in the former. PouchDB handles the insertions.
startBlock: Tornado.Data.Onchain.getInstanceDeployBlockNumSync("1", "eth", "0.1") startBlock: Tornado.Data.Onchain.getInstanceDeployBlockNumSync("1", "eth", "0.1")
} }
) )
// Export as archive again! // Export as archive again!
await core.exportAsArchive('Deposits1ETH0.1') await core.exportAsArchive('Deposits1ETH0.1')
} }
sync() sync()
@ -147,8 +157,7 @@ sync()
```ts ```ts
import * as Tornado from "@tornado/sdk" import * as Tornado from "@tornado/sdk"
/// You can implement this however you want. let logListener = function (...args: any[]) {
function logListener(...args: any[]) {
if (args.length === 3) { if (args.length === 3) {
console.debug(`\nSync will be started with SB: ${args[0]}, TB: ${args[1]}, BD: ${args[2]}\n`) console.debug(`\nSync will be started with SB: ${args[0]}, TB: ${args[1]}, BD: ${args[2]}\n`)
} else if (args.length == 2) { } else if (args.length == 2) {
@ -157,26 +166,31 @@ function logListener(...args: any[]) {
} }
async function sync() { async function sync() {
// Get a torified ethers v5 provider. // Get a torified ethers v5 provider.
const provider = new Tornado.Web.TorProvider("https://eth.llamarpc.com", { port: 9150 }) const provider = new Tornado.Web.TorProvider("https://eth.llamarpc.com", { port: 9150 })
// Get the core Tornado Cash logic. // Get the core Tornado Cash logic.
const core = new Tornado.Core() const core = new Tornado.Core()
// Connect the provider (necessary) // Connect the provider (necessary)
await core.connect(provider) await core.connect(provider)
// Get the instance to sync // Get the instance to sync
const instance = await core.getInstance("eth", 0.1) const instance = core.getInstance("eth", 0.1)
// Log // Log
core.on('debug', logListener) core.on('debug', logListener)
// Sync! // Sync!
await core.syncDeposits(instance) await core.syncDeposits(instance,
{
// Always sync from start if we want to do multiple RPCs
startBlock: Tornado.Data.Onchain.getInstanceDeployBlockNumSync("1", "eth", "0.1")
}
)
// Log // Log
core.off('debug', logListener) core.off('debug', logListener)
} }
sync() sync()

@ -13,7 +13,8 @@
<div class="tsd-page-title"> <div class="tsd-page-title">
<h2>@tornado/sdk</h2></div> <h2>@tornado/sdk</h2></div>
<div class="tsd-panel tsd-typography"><a id="md:tornado-cash-sdk" class="tsd-anchor"></a><h1><a href="#md:tornado-cash-sdk">Tornado Cash SDK</a></h1><p>SDK to integrate your protocol with Tornado Cash.</p> <div class="tsd-panel tsd-typography"><a id="md:tornado-cash-sdk" class="tsd-anchor"></a><h1><a href="#md:tornado-cash-sdk">Tornado Cash SDK</a></h1><p>SDK to integrate your protocol with Tornado Cash.</p>
<p><a href="./docs/ABOUT.md">Check out the docs here.</a></p> <p><a href="./docs/ABOUT.md">Please check out the docs here.</a></p>
<p>You SHOULD familiarize yourself with features <a href="./docs/EXPERIMENTAL.md">still considered experimental</a>.</p>
<p>You may also read, <a href="./docs/TESTS.md">a note on testing.</a></p> <p>You may also read, <a href="./docs/TESTS.md">a note on testing.</a></p>
<p>Contributions are welcome, we are here for freedom after all!</p> <p>Contributions are welcome, we are here for freedom after all!</p>
<p>See <a href="./HISTORY.md">HISTORY.md</a> for a development log.</p> <p>See <a href="./HISTORY.md">HISTORY.md</a> for a development log.</p>

@ -10,7 +10,7 @@
"crypto", "crypto",
"zk" "zk"
], ],
"version": "0.0.8-alpha", "version": "0.0.9-alpha",
"engines": { "engines": {
"node": "^18" "node": "^18"
}, },
@ -104,5 +104,6 @@
"tsconfig-paths@4.2.0": { "tsconfig-paths@4.2.0": {
"unplugged": true "unplugged": true
} }
} },
"stableVersion": "0.0.8-alpha"
} }