Commit 9f863721 authored by XFT's avatar XFT
Browse files

Public release.

parent dc705ca0
Pipeline #25 failed with stages
in 0 seconds
# offshift-commandline-public
# Offshift anon CLI
This is a commandline interface as well as text interface interacting with the Offshift anon platform.
## Features
- Console User Interface for easy desktop usage
- Local Storage of Deposit Notes
- Commandline usage for automation
The main purpose of this tool is to offer a portable, easy to audit way to utilize the Offshift anon protocol, as well as giving potential integrators an easy route to automation.
## Installation
- Requires NodeJS v16+ and npm.
- Extract to desired folder.
- Run `npm install`.
- Edit the `config.json` with your deposit private key and your preferred RPC provider.
- `npm run start` or `node main` starts the application in CUI mode.
# Usage
The protocol has three primary functions, which can be utilized from the CLI/CUI. Burning XFT for a note, Redeeming a note for anonAssets, and Simple Shifting from an anonAsset back to XFT.
When starting up, the interface will fetch a configuration from your selected relayer, and then load its' supported Shifters.
**Note:** *Only Shifters registered to Offshift's Shifter Storage contract (0x8997F152A1DA95Fc7f966bDdD64571c9ad11075e) are loaded with the CLI, in order to prevent malicious relayers from compromising your usage of the protocol.*
`BURN XFT & CONVERT TO DEPOSIT NOTE` will bring up a list of Shifters. After choosing one, you will burn XFT and generate a deposit note for that Shifter.
`BURN DEPOSIT NOTE & MINT ANON ASSET` will bring up a list of unspent deposit notes. After choosing one, you will be asked for a Withdrawal address. Finally, the application will generate and redeem a zero-knowledge redemption proof, resulting in the anonAsset being minted to your selected address.
`SHIFT ANON ASSET TO XFT` will bring up a list of supported anonAssets for you to choose from. After choosng one, you will be asked for the amount you'd like to Shift. Finally, your asset will be Shifted back to XFT via burn & mint.
`VIEW BALANCES` will bring up an aggregated list of anonAssets and your balances of those assets (but only for the wallet whose key is currently loaded).
For commandline usage, see the [CLI Mode](#cli-mode) section.
# Warnings and Precautions
Please treat the working directory as a sensitive environment, as private keys and redemption keys exist in the configuration file and inside the SQLite database.
**The `notes.sqlite` file that gets created contains all relevant secrets required for withdrawing your deposits. Treat it like you would an unencrypted wallet.dat file. This is the only data that can be used to redeem your deposits.**
# CLI Mode
Flags can be passed to the application in order to operate in CLI-only mode. You must pass an `--action` and `--shifter`, along with its arguments. The additional arguments are action dependent.
The three supported actions, and their additional required arguments are:
- `deposit`: Requires `shifter`.
- `withdraw`: Requires `shifter`, `note`, and `address`. Note must be the deposit note itself, and address is the destination address.
- `simpleShift`: Requires the `shifter` and `amount` to be shifted.
## License
MIT
{
"walletKey": "<YOUR PRIVATE KEY>",
"rpc": "<YOUR RPC>",
"storageContract": "0x8997F152A1DA95Fc7f966bDdD64571c9ad11075e",
"xftContract": "0x76BC677d444f1E9d57dAf5187ee2b7dC852745aE",
"gasLimit": 1500000,
"relayUrl": "http://relay.offshift.io"
}
\ No newline at end of file
const { parseArgs } = require("node:util")
global.commandlineController = {
getArguments: async () => {
const parsed
= parseArgs({
options: {
shifter: {
type: "string",
short: "s",
},
action: {
type: "string",
short: "a",
},
amount: {
type: "string",
short: "m",
},
note: {
type: "string",
short: "n",
},
address: {
type: "string",
short: "d",
}
},
});
return parsed.values;
},
execute: async () => {
const args = await commandlineController.getArguments();
await serviceController[args.action](args);
process.exit();
}
}
\ No newline at end of file
global.commandController = {
'c': configController.configure,
'd': serviceController.deposit,
'w': serviceController.withdraw,
's': serviceController.simpleShift,
'b': serviceController.viewBalances,
'rpc': configController.editConfig,
'walletKey': configController.editConfig,
'relayUrl': configController.editConfig,
'r': () => true,
'exit': process.exit
}
\ No newline at end of file
global.config = require('../config.json');
const fs = require('fs');
const inquirer = require('inquirer');
global.configController = {
setConfig: (key, value) => {
global.config[key] = value;
fs.writeFileSync("./config.json", JSON.stringify(config, null, 2));
},
editConfig: async (key) => {
let answers = await inquirer.prompt({
type: 'input',
name: key,
message: `Enter value for ${key}: `,
});
configController.setConfig(key, (answers[key] === 'true' ? true : (answers[key] === 'false' ? false : answers[key])));
},
configure: async () => {
let answers = await inquirer.prompt([{
type: "list",
name: "configMenu",
message: "Select an option you want to change",
choices: [
{
value: 'rpc',
name: "\tProvider RPC: " + config["rpc"],
short: "\n\tCurrent Provider: " + config["rpc"]
},
{
value: 'walletKey',
name: "\tChange Private Key",
short: "\n\tCurrent Wallet: " + cryptoController.sender
},
{
value: 'relayUrl',
name: "\tRelayer: " + config["relayUrl"],
short: "\n\tRelayer: " + config["relayUrl"]
},
{
value: 'r',
name: "\tReturn to main menu\n"
}
]
}])
await commandController[answers.configMenu](answers.configMenu);
}
}
\ No newline at end of file
const { toBN, keccak256, fromWei, toWei, randomHex } = require('web3-utils')
const pedersenHash = (data) => circomlib.babyJub.unpackPoint(circomlib.pedersenHash.hash(data))[0]
const toFixedHex = (number, length = 32) => '0x' + bigInt(number).toString(16).padStart(length * 2, '0');
const websnarkUtils = require('websnark/src/utils')
const buildGroth16 = require('websnark/src/groth16')
const stringifyBigInts = require('websnark/tools/stringifybigint').stringifyBigInts
const snarkjs = require('snarkjs')
const bigInt = snarkjs.bigInt
const MerkleTree = require('fixed-merkle-tree')
const crypto = require('crypto')
const circomlib = require('circomlib')
const Web3 = require('web3');
const rbigint = (nbytes) => snarkjs.bigInt.leBuff2int(crypto.randomBytes(nbytes))
const levels = 20;
const fs = require('fs')
const subtle = crypto.subtle;
let web3, storage, depositAccount, groth16, circuit, proving_key;
global.cryptoController = {
storageABI: require('../deps/Storage.json').abi,
shifterABI: require('../deps/XFTanon.json').abi,
tokenABI: require('../deps/Token.json').abi,
helpers: {
randomHex: randomHex,
toFixedHex: toFixedHex,
toBN: toBN,
keccak256: keccak256,
fromWei: fromWei,
toWei: toWei,
pedersenHash: pedersenHash,
rbigint: rbigint,
stringifyBigInts: stringifyBigInts,
isAddress: (address) => web3.utils.isAddress(address)
},
account: {
balance: 0,
tokenBalances: {}
},
loadFactories: async () => {
web3 = new Web3(new Web3.providers.HttpProvider(config.rpc), null, { transactionConfirmationBlocks: 1 })
storage = await new web3.eth.Contract(cryptoController.storageABI, config.storageContract);
depositAccount = web3.eth.accounts.privateKeyToAccount(config.walletKey);
web3.eth.accounts.wallet.add(depositAccount);
groth16 = await buildGroth16()
circuit = require('../deps/withdraw.json')
proving_key = fs.readFileSync('./deps/withdraw_proving_key.bin').buffer
cryptoController.sender = depositAccount.address
let relayerConfig = await (await fetch(config.relayUrl + "/config")).json()
cryptoController.relayer = {};
cryptoController.relayer.refund = toBN(relayerConfig.refund);
cryptoController.relayer.fee = toBN(relayerConfig.fee);
cryptoController.relayer.address = relayerConfig.address;
cryptoController.relayer.shifters = relayerConfig.shifters;
cryptoController.shifterList = await cryptoController.getShifters();
cryptoController.shifters = {};
cryptoController.tokens = {};
cryptoController.shifterTokens = {};
if (!cryptoController.xft) {
cryptoController.xftAddress = config.xftContract;
cryptoController.xft = await new web3.eth.Contract(cryptoController.tokenABI, cryptoController.xftAddress);
cryptoController.account.balance = await cryptoController.xft.methods.balanceOf(cryptoController.sender).call()
}
for (let i = 0; i < cryptoController.shifterList.length; i++) {
let shifter = cryptoController.shifterList[i];
cryptoController.shifters[shifter] = await new web3.eth.Contract(cryptoController.shifterABI, shifter);
let shifterToken = await cryptoController.shifters[shifter].methods.token().call();
cryptoController.tokens[shifterToken] = await new web3.eth.Contract(cryptoController.tokenABI, shifterToken);
cryptoController.shifterTokens[shifter] = shifterToken;
let newBalance = await cryptoController.tokens[shifterToken].methods.balanceOf(cryptoController.sender).call();
cryptoController.account.tokenBalances[shifterToken] = cryptoController.account.tokenBalances[shifterToken] + newBalance;
}
},
getOrSetPasswordLocally: () => {
if (!config.storagePassword) {
let password = randomHex(32);
console.log(`No password found. Creating a new one. This will be the only time it is shown. \n\n>> ${password} <<`);
configController.setConfig('storagePassword', password);
};
return config.storagePassword;
},
parseSaveNote: (saveNote) => {
const nullifier = BigInt(`0x${saveNote.slice(2, 64)}`)
const secret = BigInt(`0x${saveNote.slice(64, 126)}`)
const preimage = Buffer.concat([nullifier.leInt2Buff(31), secret.leInt2Buff(31)])
let hexNote = `0x${preimage.toString('hex')}`
const buffNote = Buffer.from(hexNote.slice(2), 'hex')
const commitment = pedersenHash(buffNote)
const CUT_LENGTH = 31
const nullifierBuff = buffNote.slice(0, CUT_LENGTH)
const nullifierHash = BigInt(pedersenHash(nullifierBuff))
return {
secret,
nullifier,
commitment,
nullifierBuff,
nullifierHash,
commitmentHex: toFixedHex(commitment),
nullifierHex: toFixedHex(nullifierHash)
}
},
refBalance: async (shifterAddress) => {
if (shifterAddress) {
let shifterToken = cryptoController.shifterTokens[shifterAddress]
let newBalance = await cryptoController.tokens[shifterToken].methods.balanceOf(cryptoController.sender).call();
cryptoController.account.tokenBalances[cryptoController.shifterTokens[shifterAddress]._address] = newBalance;
cryptoController.account.balance = await cryptoController.xft.methods.balanceOf(cryptoController.sender).call();
} else {
for (let i = 0; i < cryptoController.tokens.length; i++) {
let token = cryptoController.tokens[i];
let newBalance = await token.methods.balanceOf(cryptoController.sender).call();
cryptoController.account.tokenBalances[token._address] = newBalance;
}
}
},
xcrypt: async (data, password, shifter, address, nonce) => {
if (!nonce && nonce != 0) nonce = (await storage.methods.getDepositsLength(shifter, address, keccak256(password)).call({ from: address }));
const iv = (await subtle.digest('SHA-256', new Uint8Array(Buffer.from((password + nonce))))).slice(0, 16);
const dataBuffer = new Uint8Array(Buffer.from(data.slice(2), 'hex'));
const keyBuffer = new Uint8Array(Buffer.from(password.slice(2), 'hex'));
const key = await subtle.importKey('raw', keyBuffer, { name: 'AES-GCM' }, false, ['encrypt']);
try {
let encrypted = await subtle.encrypt({ name: 'AES-GCM', iv }, key, dataBuffer);
return "0x" + Buffer.from(encrypted).toString('hex').slice(0, 124);
} catch (err) {
console.log(err)
throw new Error("The data provided couldn't be encrypted or decrypted, please check the inputs");
}
},
generateProof: async (shifter, recipient, note) => {
const deposit = cryptoController.parseSaveNote(note);
let { fee, refund, address } = cryptoController.relayer;
let relayer = address;
let leafIndex;
const leaves = await shifter.methods.commitmentList().call()
leaves.forEach((e, i) => {
const index = toBN(i).toNumber();
if (toBN(e).eq(toBN(toFixedHex(deposit.commitment)))) {
leafIndex = index;
}
leaves[i] = toBN(e).toString(10);
});
let nullHash = deposit.nullifierHash;
tree = new MerkleTree(levels, leaves)
const { pathElements, pathIndices } = tree.path(leafIndex)
const input = stringifyBigInts({
root: tree.root(),
nullifierHash: nullHash,
relayer,
recipient,
fee,
refund,
nullifier: deposit.nullifier,
secret: deposit.secret,
pathElements: pathElements,
pathIndices: pathIndices,
})
const proofData = await websnarkUtils.genWitnessAndProve(groth16, input, circuit, proving_key)
const { proof } = websnarkUtils.toSolidityInput(proofData)
const withdrawArgs = [
toFixedHex(input.root),
toFixedHex(input.nullifierHash),
toFixedHex(input.recipient, 20),
toFixedHex(input.relayer, 20),
toFixedHex(input.fee),
toFixedHex(input.refund),
]
return { proof, withdrawArgs }
},
getShifters: async () => {
const storageShifters = await storage.methods.getAllShifters().call();
const relayerShifters = cryptoController.relayer.shifters;
return storageShifters.filter(shifter => relayerShifters.includes(shifter));
}
}
global.helpers = cryptoController.helpers;
\ No newline at end of file
const inquirer = require('inquirer');
const { toBN, toWei } = require('web3-utils')
global.serviceController = {
error: "",
deposit: async (args) => {
if (args) {
if (!args.shifter) {
console.log("No shifter specified");
return;
}
let { shifter } = args;
let shifterInstance = cryptoController.shifters[shifter];
let password = helpers.randomHex(32);
depositObject = await serviceController.prepareDeposit(shifter, cryptoController.sender, password);
await shifterInstance.methods.deposit(helpers.toFixedHex(depositObject.commitment), depositObject.encryptedNote, depositObject.passwordHash)
.send({ from: cryptoController.sender, gasLimit: config.gasLimit, value: await shifterInstance.methods.ethDenomination().call() })
await sqlite.saveNote({ note: depositObject.saveNote, shifter: shifter });
console.log(`Deposit successful.`);
await cryptoController.refBalance(shifter);
} else {
let args = {};
let allShifters = cryptoController.shifterList;
let shifterChoices = [];
shifterChoices.push(new inquirer.Separator(" "));
for (let i = 0; i < allShifters.length; i++) {
let shifterInstance = cryptoController.shifters[allShifters[i]];
let shifterToken = cryptoController.shifterTokens[allShifters[i]];
let tokenName = await cryptoController.tokens[shifterToken].methods.name().call();
let tokenDenomination = await shifterInstance.methods.denomination().call();
shifterChoices.push(
{
value: allShifters[i],
name: `${tokenName} - ${helpers.fromWei(tokenDenomination)} (${allShifters[i]})`,
});
}
shifterChoices.push(new inquirer.Separator(" "));
shifterChoices.push({
value: "exit",
name: "Exit",
});
shifterChoices.push(new inquirer.Separator(" "));
let answers = await inquirer.prompt({
type: 'list',
name: 'shifter',
message: 'Select a shifter:',
choices: shifterChoices
})
if (answers.shifter == "exit") return;
args = { shifter: answers.shifter }
await serviceController.deposit(args);
}
},
simpleShift: async (args) => {
if (args) {
if (!args.shifter) {
console.log("No shifter specified");
return;
}
if (!args.amount) {
console.log("No amount specified");
return;
}
let shifterInstance = cryptoController.shifters[args.shifter];
let { amount, shifter } = args;
let shifterToken = await cryptoController.shifters[shifter].methods.token().call();
let tokenInstance = cryptoController.tokens[shifterToken];
const tokenBalance = await tokenInstance.methods.balanceOf(cryptoController.sender).call();
if (toBN(tokenBalance) < (toBN(amount))) {
errorMsg = "Insufficient balance";
serviceController.error = errorMsg;
console.log(errorMsg);
return;
}
console.log(`Shifting ${amount} ${await tokenInstance.methods.symbol().call()} to ${cryptoController.sender}.`)
await shifterInstance.methods.simpleShift(amount, cryptoController.sender).send({ from: cryptoController.sender, gasLimit: config.gasLimit })
await cryptoController.refBalance(args.shifter);
} else {
let args = {};
let allTokens = Object.keys(cryptoController.tokens);
let tokenShifters = {};
for (let i = 0; i < allTokens.length; i++) {
for (let j = 0; j < cryptoController.shifterList.length; j++) {
let thisShifter = cryptoController.shifters[cryptoController.shifterList[j]];
let thisToken = await thisShifter.methods.token().call();
if (thisToken === allTokens[i]) {
tokenShifters[allTokens[i]] = {
shifter: cryptoController.shifterList[j],
name: await cryptoController.tokens[allTokens[i]].methods.name().call(),
}
break;
}
}
}
let shifterChoices = [];
for (let i = 0; i < Object.keys(tokenShifters).length; i++) {
shifterChoices.push({
value: tokenShifters[Object.keys(tokenShifters)[i]].shifter,
name: tokenShifters[Object.keys(tokenShifters)[i]].name,
})
}
shifterChoices.push({
value: "Exit",
name: "Exit"
});
let answers = await inquirer.prompt({
type: 'list',
name: 'shifter',
message: 'Select a token:',
pageSize: shifterChoices.length,
choices: shifterChoices
})
if (answers.shifter === "Exit") return;
let amountPrompt = await inquirer.prompt({
type: 'input',
name: 'amount',
message: 'Enter amount to shift:',
})
if (!isNaN(amountPrompt.amount)) {
let errorMsg = "No amount specified";
serviceController.error = errorMsg;
console.log(errorMsg);
return;
}
args = { shifter: answers.shifter, amount: toWei(amountPrompt.amount) }
await serviceController.simpleShift(args);
}
},
withdraw: async (args) => {
if (args) {
if (!args.shifter) {
let errorMsg = "No shifter specified";
serviceController.error = errorMsg;
console.log(errorMsg);
return;
}
if (!args.note) {
let errorMsg = "No note specified";
serviceController.error = errorMsg;
console.log(errorMsg);
return;
}
if (!args.address) {
let errorMsg = "No address specified";
serviceController.error = errorMsg;
console.log(errorMsg);
return;
}
let { note, address, shifter } = args;
let shifterInstance = cryptoController.shifters[shifter];
const { proof, withdrawArgs } = await cryptoController.generateProof(shifterInstance, address, note);
console.log("Withdrawing aUSD.")
let relayerEndpoint = config.relayUrl + "/relay";
const transaction = await fetch(relayerEndpoint, { method: "POST", headers: { 'Accept': 'application/json', 'Content-Type': 'application/json' }, body: JSON.stringify({ proof: proof, shifter: shifter, args: withdrawArgs }) })
depositObject = null;
await cryptoController.refBalance(shifter);
} else {
let args = {};
let allNotes = await sqlite.fetchNotes();
let noteChoices = [];
for (let i = 0; i < allNotes.length; i++) {
let shifterInstance = cryptoController.shifters[allNotes[i].shifter];
let shifterToken = cryptoController.shifterTokens[allNotes[i].shifter];
let tokenName = await cryptoController.tokens[shifterToken].methods.name().call();
let tokenDenomination = await shifterInstance.methods.denomination().call();
let parsed = cryptoController.parseSaveNote(allNotes[i].note);
isSpent = await shifterInstance.methods.isSpent(parsed.nullifierHex).call();
if (isSpent) {
await sqlite.spentNote(allNotes[i].note);
continue;
}
let parsedNote = cryptoController.parseSaveNote(allNotes[i].note);
let noteHex = parsedNote.commitmentHex.slice(0, 6) + "..." + parsedNote.commitmentHex.slice(-6);
allNotes[i].hex = noteHex;
allNotes[i].display = `${noteHex} (${tokenName} ${helpers.fromWei(tokenDenomination)})`
noteChoices.push(allNotes[i]);
}
noteChoices = noteChoices.map((note) => { return { name: note.display, value: note } })
noteChoices.push(new inquirer.Separator(" "));
noteChoices.push({
value: "exit",
name: "Exit",
});
noteChoices.push(new inquirer.Separator(" "));
let answers = await inquirer.prompt({
type: 'list',
name: 'note',
message: 'Select a note:',
choices: noteChoices
})
if (answers.note == "exit") return;
let withdrawalAddress = await inquirer.prompt({
type: 'input',
name: 'address',
message: 'Enter address to withdraw to:',
})
if (!helpers.isAddress(withdrawalAddress.address)) {
let errorMsg = "Invalid address specified";
serviceController.error = errorMsg;
console.log(errorMsg);
return;
}
args = { note: answers.note.note, shifter: answers.note.shifter, address: withdrawalAddress.address }
await serviceController.withdraw(args);
}
},
viewBalances: async () => {
let allTokens = Object.keys(cryptoController.tokens);
let balances = [];
await cryptoController.refBalance();
for (let i = 0; i < allTokens.length; i++) {
let token = allTokens[i];
let tokenName = await cryptoController.tokens[token].methods.name().call();
let tokenBalance = await cryptoController.tokens[token].methods.balanceOf(cryptoController.sender).call();
balances.push({ "name": `${tokenName} - ${helpers.fromWei(tokenBalance)}`, "value": tokenBalance });
};
balances.push({
value: "exit",
name: "Exit",
});
await inquirer.prompt({
type: 'list',
name: 'balance',
message: 'Token Balances:',
choices: balances
})
return;
},
prepareDeposit: async (shifter, address, password) => {
depositObject = {
secret: helpers.rbigint(31),
nullifier: helpers.rbigint(31)
}
const saveNote = `0x${depositObject.nullifier.toString(16, 'hex').padEnd(62, '0')}${depositObject.secret.toString(16, 'hex').padEnd(62, '0')}`;
const preimage = Buffer.concat([depositObject.nullifier.leInt2Buff(31), depositObject.secret.leInt2Buff(31)])
depositObject.commitment = helpers.pedersenHash(preimage);
depositObject.buffNullifierHash = helpers.pedersenHash(depositObject.nullifier.leInt2Buff(31));
depositObject.saveNote = saveNote
depositObject.encryptedNote = await cryptoController.xcrypt(saveNote, password, shifter, address, null);
depositObject.passwordHash = helpers.keccak256(password);
return depositObject
},
getAggregateDeposits: async (shifters, address, decrypted) => {
const password = cryptoController.getOrSetPasswordLocally();
let encryptedNotes = [];
let decryptedNotes = [];
let spentNotes = [];
for (let _shifter in shifters) {
shifter = shifters[_shifter];
if (password) {
let passwordHash = helpers.keccak256(password)
let shifterNotes = await xftAnon.methods.getDeposits(shifter, address, passwordHash);
shifterNotes = shifterNotes.map((note) => { return { "note": note, "shifter": shifter } });
try {
encryptedNotes = encryptedNotes.concat(shifterNotes);
} catch (e) { console.log(e) };
} else {
throw ("No password set");
}
}
let nullHashArray;
let boolSpentArray = [];
let decryptedUnspentNotes;
if (decrypted) {
for (let idx in encryptedNotes) {
let thisNote = encryptedNotes[idx];
let thisDecryptedNote = (await cryptoController.xcrypt(thisNote.note, password));
let deposited = await serviceController._getShifterContract(thisNote.shifter).methods.commitments(parseSaveNote(thisDecryptedNote).commitmentHex).call()
let spent = await serviceController._getShifterContract(thisNote.shifter).methods.isSpent(parseSaveNote(thisDecryptedNote).nullifierHex).call();
if (!spent && deposited)
decryptedNotes.push({
"note": thisDecryptedNote,
"shifter": thisNote.shifter
})
else if (spent && deposited)
spentNotes.push({
"note": thisDecryptedNote,
"shifter": thisNote.shifter
})
}
decryptedNotes = decryptedNotes
.map((note, idx) => {
return {
"note": note.note,
"shifter": note.shifter,
"commitment": parseSaveNote(note.note).commitmentHex
}
});
spentNotes = spentNotes
.map((note, idx) => {
return {
"note": note.note,
"shifter": note.shifter,
"commitment": parseSaveNote(note.note).commitmentHex
}
});
}
return (decrypted ? { decryptedNotes, spentNotes } : encryptedNotes);
}
}
\ No newline at end of file
const Sequelize = require('sequelize');
const sequelize = new Sequelize({ dialect: 'sqlite', storage: 'notes.sqlite', logging: false });
global.sqlite = {
initialize: async () => await sequelize.sync(),
fetchNotes: async () => await sqlite.Note.findAll({ where: { spent: false } }),
fetchShifterNotes: async (shifter) => await sqlite.Note.findAll({ where: { shifter: shifter } }),
spentNote: async (note) => await sqlite.Note.update({ spent: true }, { where: { note: note } }),
saveNote: async (note) => await sqlite.Note.create({ note: note.note, shifter: note.shifter, spent: false }),
Note: sequelize.define('note', {
shifter: Sequelize.STRING,
note: Sequelize.STRING,
spent: Sequelize.BOOLEAN
})
}
\ No newline at end of file
{
"contractName": "Storage",
"abi": [
{
"inputs": [
{
"internalType": "address",
"name": "_shifterContract",
"type": "address"
}
],
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "address",
"name": "shifterContract",
"type": "address"
}
],
"name": "ShifterContract",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "address",
"name": "depositor",
"type": "address"
},
{
"indexed": false,
"internalType": "bytes",
"name": "encryptedNote",
"type": "bytes"
},
{
"indexed": false,
"internalType": "bytes32",
"name": "passwordHash",
"type": "bytes32"
}
],
"name": "Store",
"type": "event"
},
{
"inputs": [
{
"internalType": "address",
"name": "",
"type": "address"
},
{
"internalType": "address",
"name": "",
"type": "address"
},
{
"internalType": "bytes32",
"name": "",
"type": "bytes32"
},
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"name": "notes",
"outputs": [
{
"internalType": "bytes",
"name": "",
"type": "bytes"
}
],
"stateMutability": "view",
"type": "function",
"constant": true
},
{
"inputs": [],
"name": "owner",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function",
"constant": true
},
{
"inputs": [
{
"internalType": "address",
"name": "_shifterContract",
"type": "address"
}
],
"name": "addShifter",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "_depositor",
"type": "address"
},
{
"internalType": "bytes",
"name": "_encryptedNote",
"type": "bytes"
},
{
"internalType": "bytes32",
"name": "_passwordHash",
"type": "bytes32"
}
],
"name": "store",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "_shifter",
"type": "address"
},
{
"internalType": "address",
"name": "_depositor",
"type": "address"
},
{
"internalType": "bytes32",
"name": "_passwordHash",
"type": "bytes32"
}
],
"name": "getLatestDeposit",
"outputs": [
{
"internalType": "bytes",
"name": "result",
"type": "bytes"
}
],
"stateMutability": "view",
"type": "function",
"constant": true
},
{
"inputs": [
{
"internalType": "address",
"name": "_shifter",
"type": "address"
},
{
"internalType": "address",
"name": "_depositor",
"type": "address"
},
{
"internalType": "bytes32",
"name": "_passwordHash",
"type": "bytes32"
}
],
"name": "getDeposits",
"outputs": [
{
"internalType": "bytes[]",
"name": "result",
"type": "bytes[]"
}
],
"stateMutability": "view",
"type": "function",
"constant": true
},
{
"inputs": [
{
"internalType": "address",
"name": "_shifter",
"type": "address"
},
{
"internalType": "address",
"name": "_depositor",
"type": "address"
},
{
"internalType": "bytes32",
"name": "_passwordHash",
"type": "bytes32"
}
],
"name": "getDepositsLength",
"outputs": [
{
"internalType": "uint256",
"name": "length",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function",
"constant": true
},
{
"inputs": [
{
"internalType": "address",
"name": "_shifter",
"type": "address"
},
{
"internalType": "address",
"name": "_depositor",
"type": "address"
},
{
"internalType": "bytes32",
"name": "_passwordHash",
"type": "bytes32"
},
{
"internalType": "uint256",
"name": "_index",
"type": "uint256"
}
],
"name": "getDepositByIndex",
"outputs": [
{
"internalType": "bytes",
"name": "result",
"type": "bytes"
}
],
"stateMutability": "view",
"type": "function",
"constant": true
},
{
"inputs": [],
"name": "getShifterCount",
"outputs": [
{
"internalType": "uint256",
"name": "count",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function",
"constant": true
},
{
"inputs": [
{
"internalType": "uint256",
"name": "index",
"type": "uint256"
}
],
"name": "getShifterAtIndex",
"outputs": [
{
"internalType": "address",
"name": "shifter",
"type": "address"
}
],
"stateMutability": "view",
"type": "function",
"constant": true
},
{
"inputs": [
{
"internalType": "address",
"name": "_shifterContract",
"type": "address"
}
],
"name": "isShifter",
"outputs": [
{
"internalType": "bool",
"name": "isShifter",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function",
"constant": true
},
{
"inputs": [],
"name": "getAllShifters",
"outputs": [
{
"internalType": "address[]",
"name": "shifters",
"type": "address[]"
}
],
"stateMutability": "view",
"type": "function",
"constant": true
}
]
}
\ No newline at end of file
{
"contractName": "aUSDMock",
"abi": [
{
"inputs": [
{
"internalType": "string",
"name": "name_",
"type": "string"
},
{
"internalType": "string",
"name": "symbol_",
"type": "string"
}
],
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "owner",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "spender",
"type": "address"
},
{
"indexed": false,
"internalType": "uint256",
"name": "value",
"type": "uint256"
}
],
"name": "Approval",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "bytes32",
"name": "role",
"type": "bytes32"
},
{
"indexed": true,
"internalType": "bytes32",
"name": "previousAdminRole",
"type": "bytes32"
},
{
"indexed": true,
"internalType": "bytes32",
"name": "newAdminRole",
"type": "bytes32"
}
],
"name": "RoleAdminChanged",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "bytes32",
"name": "role",
"type": "bytes32"
},
{
"indexed": true,
"internalType": "address",
"name": "account",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "sender",
"type": "address"
}
],
"name": "RoleGranted",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "bytes32",
"name": "role",
"type": "bytes32"
},
{
"indexed": true,
"internalType": "address",
"name": "account",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "sender",
"type": "address"
}
],
"name": "RoleRevoked",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "from",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "to",
"type": "address"
},
{
"indexed": false,
"internalType": "uint256",
"name": "value",
"type": "uint256"
}
],
"name": "Transfer",
"type": "event"
},
{
"inputs": [],
"name": "BURNER_ROLE",
"outputs": [
{
"internalType": "bytes32",
"name": "",
"type": "bytes32"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "DEFAULT_ADMIN_ROLE",
"outputs": [
{
"internalType": "bytes32",
"name": "",
"type": "bytes32"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "MINTER_ROLE",
"outputs": [
{
"internalType": "bytes32",
"name": "",
"type": "bytes32"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "owner",
"type": "address"
},
{
"internalType": "address",
"name": "spender",
"type": "address"
}
],
"name": "allowance",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "spender",
"type": "address"
},
{
"internalType": "uint256",
"name": "amount",
"type": "uint256"
}
],
"name": "approve",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "account",
"type": "address"
}
],
"name": "balanceOf",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "decimals",
"outputs": [
{
"internalType": "uint8",
"name": "",
"type": "uint8"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "spender",
"type": "address"
},
{
"internalType": "uint256",
"name": "subtractedValue",
"type": "uint256"
}
],
"name": "decreaseAllowance",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "bytes32",
"name": "role",
"type": "bytes32"
}
],
"name": "getRoleAdmin",
"outputs": [
{
"internalType": "bytes32",
"name": "",
"type": "bytes32"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "bytes32",
"name": "role",
"type": "bytes32"
},
{
"internalType": "uint256",
"name": "index",
"type": "uint256"
}
],
"name": "getRoleMember",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "bytes32",
"name": "role",
"type": "bytes32"
}
],
"name": "getRoleMemberCount",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "bytes32",
"name": "role",
"type": "bytes32"
},
{
"internalType": "address",
"name": "account",
"type": "address"
}
],
"name": "grantRole",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "bytes32",
"name": "role",
"type": "bytes32"
},
{
"internalType": "address",
"name": "account",
"type": "address"
}
],
"name": "hasRole",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "spender",
"type": "address"
},
{
"internalType": "uint256",
"name": "addedValue",
"type": "uint256"
}
],
"name": "increaseAllowance",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "name",
"outputs": [
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "bytes32",
"name": "role",
"type": "bytes32"
},
{
"internalType": "address",
"name": "account",
"type": "address"
}
],
"name": "renounceRole",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "bytes32",
"name": "role",
"type": "bytes32"
},
{
"internalType": "address",
"name": "account",
"type": "address"
}
],
"name": "revokeRole",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "symbol",
"outputs": [
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "totalSupply",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "recipient",
"type": "address"
},
{
"internalType": "uint256",
"name": "amount",
"type": "uint256"
}
],
"name": "transfer",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "sender",
"type": "address"
},
{
"internalType": "address",
"name": "recipient",
"type": "address"
},
{
"internalType": "uint256",
"name": "amount",
"type": "uint256"
}
],
"name": "transferFrom",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "to",
"type": "address"
},
{
"internalType": "uint256",
"name": "amount",
"type": "uint256"
}
],
"name": "mint",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "from",
"type": "address"
},
{
"internalType": "uint256",
"name": "amount",
"type": "uint256"
}
],
"name": "burn",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
}
]
}
\ No newline at end of file
{
"contractName": "XFTMock",
"abi": [
{
"inputs": [],
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "owner",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "spender",
"type": "address"
},
{
"indexed": false,
"internalType": "uint256",
"name": "value",
"type": "uint256"
}
],
"name": "Approval",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "bytes32",
"name": "role",
"type": "bytes32"
},
{
"indexed": true,
"internalType": "bytes32",
"name": "previousAdminRole",
"type": "bytes32"
},
{
"indexed": true,
"internalType": "bytes32",
"name": "newAdminRole",
"type": "bytes32"
}
],
"name": "RoleAdminChanged",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "bytes32",
"name": "role",
"type": "bytes32"
},
{
"indexed": true,
"internalType": "address",
"name": "account",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "sender",
"type": "address"
}
],
"name": "RoleGranted",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "bytes32",
"name": "role",
"type": "bytes32"
},
{
"indexed": true,
"internalType": "address",
"name": "account",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "sender",
"type": "address"
}
],
"name": "RoleRevoked",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "from",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "to",
"type": "address"
},
{
"indexed": false,
"internalType": "uint256",
"name": "value",
"type": "uint256"
}
],
"name": "Transfer",
"type": "event"
},
{
"inputs": [],
"name": "BURNER_ROLE",
"outputs": [
{
"internalType": "bytes32",
"name": "",
"type": "bytes32"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "DEFAULT_ADMIN_ROLE",
"outputs": [
{
"internalType": "bytes32",
"name": "",
"type": "bytes32"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "MINTER_ROLE",
"outputs": [
{
"internalType": "bytes32",
"name": "",
"type": "bytes32"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "owner",
"type": "address"
},
{
"internalType": "address",
"name": "spender",
"type": "address"
}
],
"name": "allowance",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "spender",
"type": "address"
},
{
"internalType": "uint256",
"name": "amount",
"type": "uint256"
}
],
"name": "approve",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "account",
"type": "address"
}
],
"name": "balanceOf",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "decimals",
"outputs": [
{
"internalType": "uint8",
"name": "",
"type": "uint8"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "spender",
"type": "address"
},
{
"internalType": "uint256",
"name": "subtractedValue",
"type": "uint256"
}
],
"name": "decreaseAllowance",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "bytes32",
"name": "role",
"type": "bytes32"
}
],
"name": "getRoleAdmin",
"outputs": [
{
"internalType": "bytes32",
"name": "",
"type": "bytes32"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "bytes32",
"name": "role",
"type": "bytes32"
},
{
"internalType": "uint256",
"name": "index",
"type": "uint256"
}
],
"name": "getRoleMember",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "bytes32",
"name": "role",
"type": "bytes32"
}
],
"name": "getRoleMemberCount",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "bytes32",
"name": "role",
"type": "bytes32"
},
{
"internalType": "address",
"name": "account",
"type": "address"
}
],
"name": "grantRole",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "bytes32",
"name": "role",
"type": "bytes32"
},
{
"internalType": "address",
"name": "account",
"type": "address"
}
],
"name": "hasRole",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "spender",
"type": "address"
},
{
"internalType": "uint256",
"name": "addedValue",
"type": "uint256"
}
],
"name": "increaseAllowance",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "name",
"outputs": [
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "bytes32",
"name": "role",
"type": "bytes32"
},
{
"internalType": "address",
"name": "account",
"type": "address"
}
],
"name": "renounceRole",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "bytes32",
"name": "role",
"type": "bytes32"
},
{
"internalType": "address",
"name": "account",
"type": "address"
}
],
"name": "revokeRole",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "symbol",
"outputs": [
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "totalSupply",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "recipient",
"type": "address"
},
{
"internalType": "uint256",
"name": "amount",
"type": "uint256"
}
],
"name": "transfer",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "sender",
"type": "address"
},
{
"internalType": "address",
"name": "recipient",
"type": "address"
},
{
"internalType": "uint256",
"name": "amount",
"type": "uint256"
}
],
"name": "transferFrom",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "to",
"type": "address"
},
{
"internalType": "uint256",
"name": "amount",
"type": "uint256"
}
],
"name": "mint",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "from",
"type": "address"
},
{
"internalType": "uint256",
"name": "amount",
"type": "uint256"
}
],
"name": "burn",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
}
]
}
\ No newline at end of file
{
"contractName": "XFTanon",
"abi": [
{
"inputs": [
{
"internalType": "contract IVerifier",
"name": "_verifier",
"type": "address"
},
{
"internalType": "contract IHasher",
"name": "_hasher",
"type": "address"
},
{
"internalType": "contract IStorage",
"name": "_storage",
"type": "address"
},
{
"internalType": "uint256",
"name": "_denomination",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "_ethDenomination",
"type": "uint256"
},
{
"internalType": "uint32",
"name": "_merkleTreeHeight",
"type": "uint32"
},
{
"internalType": "contract ElasticIERC20",
"name": "_xft",
"type": "address"
},
{
"internalType": "contract ElasticIERC20",
"name": "_token",
"type": "address"
},
{
"internalType": "contract IOracle",
"name": "_oracle",
"type": "address"
},
{
"internalType": "address",
"name": "_xftPool",
"type": "address"
},
{
"internalType": "address",
"name": "_tokenPool",
"type": "address"
},
{
"internalType": "address",
"name": "_weth9",
"type": "address"
},
{
"internalType": "address",
"name": "_chainlinkFeed",
"type": "address"
},
{
"internalType": "uint32",
"name": "_interval",
"type": "uint32"
},
{
"internalType": "uint256",
"name": "_flexFeeThreshold",
"type": "uint256"
}
],
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "bytes32",
"name": "commitment",
"type": "bytes32"
},
{
"indexed": false,
"internalType": "uint32",
"name": "leafIndex",
"type": "uint32"
},
{
"indexed": false,
"internalType": "uint256",
"name": "timestamp",
"type": "uint256"
}
],
"name": "Deposit",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "previousOwner",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "newOwner",
"type": "address"
}
],
"name": "OwnershipTransferred",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "address",
"name": "account",
"type": "address"
}
],
"name": "Paused",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "address",
"name": "account",
"type": "address"
}
],
"name": "Unpaused",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "address",
"name": "to",
"type": "address"
},
{
"indexed": false,
"internalType": "bytes32",
"name": "nullifierHash",
"type": "bytes32"
},
{
"indexed": true,
"internalType": "address",
"name": "relayer",
"type": "address"
},
{
"indexed": false,
"internalType": "uint256",
"name": "fee",
"type": "uint256"
}
],
"name": "Withdrawal",
"type": "event"
},
{
"inputs": [],
"name": "FIELD_SIZE",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "ROOT_HISTORY_SIZE",
"outputs": [
{
"internalType": "uint32",
"name": "",
"type": "uint32"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "ZERO_VALUE",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"name": "allCommitments",
"outputs": [
{
"internalType": "bytes32",
"name": "",
"type": "bytes32"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "chainlinkFeed",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "commitmentList",
"outputs": [
{
"internalType": "bytes32[]",
"name": "",
"type": "bytes32[]"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "bytes32",
"name": "",
"type": "bytes32"
}
],
"name": "commitments",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "currentRootIndex",
"outputs": [
{
"internalType": "uint32",
"name": "",
"type": "uint32"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "denomination",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "bytes32",
"name": "_commitment",
"type": "bytes32"
},
{
"internalType": "bytes",
"name": "_encryptedNote",
"type": "bytes"
},
{
"internalType": "bytes32",
"name": "_passwordHash",
"type": "bytes32"
}
],
"name": "deposit",
"outputs": [],
"stateMutability": "payable",
"type": "function"
},
{
"inputs": [],
"name": "ethDenomination",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"name": "filledSubtrees",
"outputs": [
{
"internalType": "bytes32",
"name": "",
"type": "bytes32"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "flexFeeThreshold",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "getLastRoot",
"outputs": [
{
"internalType": "bytes32",
"name": "",
"type": "bytes32"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "contract IHasher",
"name": "_hasher",
"type": "address"
},
{
"internalType": "bytes32",
"name": "_left",
"type": "bytes32"
},
{
"internalType": "bytes32",
"name": "_right",
"type": "bytes32"
}
],
"name": "hashLeftRight",
"outputs": [
{
"internalType": "bytes32",
"name": "",
"type": "bytes32"
}
],
"stateMutability": "pure",
"type": "function"
},
{
"inputs": [],
"name": "hasher",
"outputs": [
{
"internalType": "contract IHasher",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "interval",
"outputs": [
{
"internalType": "uint32",
"name": "",
"type": "uint32"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "bytes32",
"name": "_root",
"type": "bytes32"
}
],
"name": "isKnownRoot",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "bytes32",
"name": "_nullifierHash",
"type": "bytes32"
}
],
"name": "isSpent",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "bytes32[]",
"name": "_nullifierHashes",
"type": "bytes32[]"
}
],
"name": "isSpentArray",
"outputs": [
{
"internalType": "bool[]",
"name": "spent",
"type": "bool[]"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "levels",
"outputs": [
{
"internalType": "uint32",
"name": "",
"type": "uint32"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "nextIndex",
"outputs": [
{
"internalType": "uint32",
"name": "",
"type": "uint32"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "noteStorage",
"outputs": [
{
"internalType": "contract IStorage",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "bytes32",
"name": "",
"type": "bytes32"
}
],
"name": "nullifierHashes",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "oracle",
"outputs": [
{
"internalType": "contract IOracle",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "oracleActive",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "owner",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "paused",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "renounceOwnership",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"name": "roots",
"outputs": [
{
"internalType": "bytes32",
"name": "",
"type": "bytes32"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "token",
"outputs": [
{
"internalType": "contract ElasticIERC20",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "tokenPool",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "tokenPrice",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "newOwner",
"type": "address"
}
],
"name": "transferOwnership",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "verifier",
"outputs": [
{
"internalType": "contract IVerifier",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "weth9",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "bytes",
"name": "_proof",
"type": "bytes"
},
{
"internalType": "bytes32",
"name": "_root",
"type": "bytes32"
},
{
"internalType": "bytes32",
"name": "_nullifierHash",
"type": "bytes32"
},
{
"internalType": "address payable",
"name": "_recipient",
"type": "address"
},
{
"internalType": "address payable",
"name": "_relayer",
"type": "address"
},
{
"internalType": "uint256",
"name": "_fee",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "_refund",
"type": "uint256"
}
],
"name": "withdraw",
"outputs": [],
"stateMutability": "payable",
"type": "function"
},
{
"inputs": [],
"name": "xft",
"outputs": [
{
"internalType": "contract ElasticIERC20",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "xftPool",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "i",
"type": "uint256"
}
],
"name": "zeros",
"outputs": [
{
"internalType": "bytes32",
"name": "",
"type": "bytes32"
}
],
"stateMutability": "pure",
"type": "function"
},
{
"inputs": [],
"name": "pause",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint32",
"name": "_interval",
"type": "uint32"
}
],
"name": "setInterval",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "_threshold",
"type": "uint256"
}
],
"name": "setFlexFeeThreshold",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "_amount",
"type": "uint256"
},
{
"internalType": "address",
"name": "_recipient",
"type": "address"
}
],
"name": "simpleShift",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "getDenomination",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "_amount",
"type": "uint256"
}
],
"name": "getCost",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
}
]
}
\ No newline at end of file
This diff is collapsed.
File added
['config', 'crypto', 'sqlite', 'services', 'commands', 'cli'].forEach(i => require(`./controllers/${i}`));
const inquirer = require('inquirer');
const main = async () => {
await sqlite.initialize();
await cryptoController.loadFactories();
if (process.argv.length > 3) commandlineController.execute();
else mainMenu();
}
const mainMenu = async () => {
let answers = await inquirer.prompt([{
type: "list",
name: "menu",
message: `
XFT Anon CLI (Mainnet Edition)
XFT Balance: ${parseInt(helpers.fromWei(cryptoController.account.balance))}
\x1b[31m${serviceController.error}\x1b[0m
Select an option:\n`,
choices: [
{
value: 'c',
name: "\tCONFIG",
short: "\n\tEditing Config"
},
{
value: 'd',
name: "\tBURN XFT & CONVERT TO DEPOSIT NOTE",
short: "\n\tMaking a Deposit"
},
{
value: 'w',
name: "\tBURN DEPOSIT NOTE & MINT ANON ASSET",
short: "\n\tMaking a Withdrawal"
},
{
value: 's',
name: "\tSHIFT ANON ASSET TO XFT",
short: "\n\tPerforming a Shift to XFT"
},
{
value: 'b',
name:'\tVIEW BALANCES',
short: "\n\tViewing Token Balances"
},
{
value: 'exit',
name: "\tEXIT\n",
}
]
}])
serviceController.error = "";
await commandController[answers.menu]();
mainMenu();
}
main();
\ No newline at end of file
{
"name": "xftanon-cli",
"version": "1.0.0",
"description": "CLI tool for interacting with the XFT anon platform.",
"main": "main.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "node --no-warnings main"
},
"author": "Offshift Team",
"license": "MIT",
"engines": {
"node": "^18.15.0"
},
"dependencies": {
"circom": "^0.0.35",
"circomlib": "git+https://github.com/tornadocash/circomlib.git#c372f14d324d57339c88451834bf2824e73bbdbc",
"fixed-merkle-tree": "^0.6.0",
"inquirer": "^8.0.0",
"node-fetch": "^3.2.10",
"sequelize": "^6.28.0",
"snarkjs": "git+https://github.com/tornadocash/snarkjs.git#869181cfaf7526fe8972073d31655493a04326d5",
"sqlite3": "^5.1.4",
"web3": "^1.3.4",
"web3-utils": "^1.7.4",
"websnark": "git+https://github.com/tornadocash/websnark.git#4c0af6a8b65aabea3c09f377f63c44e7a58afa6d"
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment