diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 36da2336b..42c43efdc 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -1,6 +1,7 @@ - ## Expected Behaviour + diff --git a/.prettierignore b/.prettierignore index 4537df6c3..897fe0ade 100644 --- a/.prettierignore +++ b/.prettierignore @@ -16,5 +16,5 @@ package.json # packages packages/contract-addresses/addresses/ packages/contract-artifacts/artifacts/ -packages/graph/ +packages/documentation/*/apis/ packages/extension/ diff --git a/package.json b/package.json index f014b45d9..2f06ef7f4 100644 --- a/package.json +++ b/package.json @@ -41,7 +41,7 @@ "lerna": "lerna", "lint": "yarn wsrun --package $PKG --parallel -c lint", "prettier": "prettier --config .prettierrc --write '**/*.{js,jsx,json,md}'", - "prettier:ci": "prettier --config .prettierrc --list-different '**/*.{js,jsx,json,md}'", + "prettier:ci": "yarn prettier && prettier --config .prettierrc --list-different '**/*.{js,jsx,json,md}'", "publish:docs": "yarn wsrun --package $PKG --parallel -c --if has:changed publish:docs", "rebuild": "run-s clean build", "script:build:artifacts": "node ./packages/monorepo-scripts/artifacts/build.js", diff --git a/packages/documentation/package.json b/packages/documentation/package.json index f1b32436b..1b1abee0e 100644 --- a/packages/documentation/package.json +++ b/packages/documentation/package.json @@ -7,9 +7,11 @@ }, "description": "AZTEC Protocol documentation based on React Styleguidist", "scripts": { - "build": "truffle compile --all && styleguidist build && yarn copy", + "build": "truffle compile --all && styleguidist build && yarn copyApis && yarn copyImages", "clean": "shx rm -rf ./build ./dist ./public || true", - "copy": "find ../extension/src/client/apis -iregex '.(ZkNote|Account|ZkAsset).' -exec cp {} ./public/apis \\;", + "copyApis": "cp -r src/apis public/apis", + "copy:local": "find -E ../extension/src/client/apis -regex '.*(Zk|Account).*' -exec cp {} ./src/apis \\;", + "copyImages": "cp -r ./images ./public", "generateStyles": "guacamole generateStyles", "lint": "eslint --ignore-path .eslintignore .", "start": "yarn styleguide", diff --git a/packages/documentation/src/apis/Account.js b/packages/documentation/src/apis/Account.js new file mode 100644 index 000000000..b3b28e08f --- /dev/null +++ b/packages/documentation/src/apis/Account.js @@ -0,0 +1,131 @@ +import { + note as noteUtils, +} from 'aztec.js'; +import uniq from 'lodash/uniq'; +import Web3Service from '~/client/services/Web3Service'; +import ConnectionService from '~/client/services/ConnectionService'; +import ApiError from '~/client/utils/ApiError'; + +const dataProperties = [ + 'address', + 'linkedPublicKey', + 'spendingPublicKey', +]; + +class Account { + constructor(account) { + dataProperties.forEach((key) => { + this[key] = account[key] || ''; + }); + this.id = account.address; + } + + get registered() { + return !!this.linkedPublicKey; + } + + /** + * + * @function user.createNote + * @description Description: Create an AZTEC note owned by the user. + * + * @param {Integer} value Value of the note. + * + * @param {[Address]} userAccess Optional array of address that will be granted view access to the note value. + * + * @returns {AztecNote} note An AZTEC note owned by the user. + * + */ + async createNote(value, userAccess = []) { + if (!this.registered) { + throw new ApiError('user.unregistered', { + fn: 'createNote', + }); + } + + let noteAccess = []; + if (userAccess && userAccess.length) { + ({ + accounts: noteAccess, + } = await ConnectionService.query( + 'users', + { + where: { + address_in: uniq(userAccess), + }, + }, + ` + address + linkedPublicKey + `, + ) || {}); + } + + return noteUtils.create( + this.spendingPublicKey, + value, + noteAccess, + this.address, + ); + } + + /** + * + * @function user.encryptMessage + * @description Description: Encrypt a message using the user's public key. + * + * @param {String} message Message to be encrypted. + * + * @returns {HexString} encrypted An encrypted message. + * + */ + async encryptMessage(message) { + if (!this.registered) { + throw new ApiError('user.unregistered', { + fn: 'encryptMessage', + }); + } + + const { encrypted } = await ConnectionService.query( + 'encryptMessage', + { + address: this.address, + linkedPublicKey: this.linkedPublicKey, + message, + }, + ) || {}; + + return encrypted; + } + + /** + * + * @function user.decryptMessage + * @description Description: Decrypt a message using the user's private key. + * This method is available only for current user. + * + * @param {HexString} encrypted An encrypted message. + * + * @returns {String} message The decrypted message. + * + */ + async decryptMessage(message) { + if (this.address !== Web3Service.account.address) { + throw new ApiError('user.logout', { + fn: 'decryptMessage', + }); + } + + const { decrypted } = await ConnectionService.query( + 'decryptMessage', + { + address: this.address, + message, + }, + ) || {}; + + return decrypted; + } +} + +export default Account; diff --git a/packages/documentation/src/apis/ZkAsset.js b/packages/documentation/src/apis/ZkAsset.js new file mode 100644 index 000000000..1293cfa29 --- /dev/null +++ b/packages/documentation/src/apis/ZkAsset.js @@ -0,0 +1,678 @@ +import BN from 'bn.js'; +import { + tokenToNoteValue, + noteToTokenValue, + recoverJoinSplitProof, +} from '~/utils/transformData'; +import Web3Service from '~/client/services/Web3Service'; +import ConnectionService from '~/client/services/ConnectionService'; +import ContractError from '~/client/utils/ContractError'; +import ApiError from '~/client/utils/ApiError'; +import parseInputTransactions from '~/client/utils/parseInputTransactions'; +import parseInputInteger from '~/client/utils/parseInputInteger'; +import SubscriptionManager from './SubscriptionManager'; + +const dataProperties = [ + 'address', + 'linkedTokenAddress', + 'scalingFactor', + 'canAdjustSupply', + 'canConvert', + 'token', +]; + +export default class ZkAsset { + constructor({ + id, + ...asset + } = {}) { + dataProperties.forEach((key) => { + this[key] = asset[key]; + }); + this.id = id; + this.subscriptions = new SubscriptionManager(); + } + + get valid() { + return !!this.address; + } + + isValid() { + return !!this.address; + } + + /** + * + * @function zkAsset.balance + * @description Description: Get the balance of a ZkAsset. + * + * @returns {Integer} balance Balance of the ZkAsset. + * + */ + async balance() { + const { balance } = await ConnectionService.query( + 'assetBalance', + { id: this.id }, + ) || {}; + + return balance || 0; + } + + /** + * + * @function zkAsset.totalSupplyOfLinkedToken + * @description Description: Get the total supply of the ERC20 token linked to the ZkAsset + * + * @returns {BigNumber} totalSupply Token number of ERC20 tokens + * + */ + async totalSupplyOfLinkedToken() { + if (!this.linkedTokenAddress) { + throw new ApiError('zkAsset.private', { + fn: 'totalSupplyOfLinkedToken', + }); + } + + let totalSupply = 0; + try { + totalSupply = await Web3Service + .useContract('ERC20') + .at(this.linkedTokenAddress) + .method('totalSupply') + .call(); + } catch (error) { + throw new ContractError('erc20.totalSupply'); + } + + return new BN(totalSupply); + } + + /** + * @function zkAsset.balanceOfLinkedToken + * @description Description: Get the linked ERC20 token balance for an address. + * + * @param {String} account Optional Ethereum address for which the balance of the linked ERC20 token is being fetched. + * Will use the current user's address if not defined. + * + * @returns {BigNumber} balance Number of linked ERC20 tokens held by the `account`. + * + */ + balanceOfLinkedToken = async (account) => { + if (!this.linkedTokenAddress) { + throw new ApiError('zkAsset.private', { + fn: 'balanceOfLinkedToken', + }); + } + + let balance = 0; + let accountAddress = account; + if (!accountAddress) { + ({ + address: accountAddress, + } = Web3Service.account); + } + + try { + balance = await Web3Service + .useContract('ERC20') + .at(this.linkedTokenAddress) + .method('balanceOf') + .call(accountAddress); + } catch (error) { + throw new ContractError('erc20.balanceOf', { + messageOptions: { + account: accountAddress, + }, + }); + } + + return new BN(balance); + }; + + /** + * + * @function zkAsset.allowanceOfLinkedToken + * @description Description: Get the number of linked ERC20 tokens a spender is allowed to spend on behalf of an owner. + * + * @param {String} owner Optional Ethereum address which owns linked ERC20 tokens. + * Will use the current user's address if not defined. + * + * @param {String} spender Optional Ethereum address that is expected to have previously been approved to spend ERC20 tokens on behalf of the owner. + * Will use the address of `ACE` contract if not defined. + * + * @returns {BigNumber} allowance Number of linked ERC20 tokens the spender has been approved to spend on the owner's behalf. + * + */ + allowanceOfLinkedToken = async (owner = '', spender = '') => { + if (!this.linkedTokenAddress) { + throw new ApiError('zkAsset.private', { + fn: 'allowanceOfLinkedToken', + }); + } + + let allowance = 0; + let ownerAddress = owner; + if (!ownerAddress) { + ({ + address: ownerAddress, + } = Web3Service.account); + } + + let spenderAddress = spender; + if (!spenderAddress) { + spenderAddress = Web3Service.getAddress('ACE'); + } + + try { + allowance = await Web3Service + .useContract('ERC20') + .at(this.linkedTokenAddress) + .method('allowance') + .call( + ownerAddress, + spenderAddress, + ); + } catch (error) { + throw new ContractError('erc20.allowance', { + owner: ownerAddress, + spender: spenderAddress, + }); + } + + return new BN(allowance); + }; + + /** + * + * @function zkAsset.subscribeToBalance + * @description Description: Get notified whenever the balance of an asset is changed. + * + * @param {Function} callback A listener, which will receive the new value whenever the balance is changed: + * + * - callback(*balance*): Where balance is an Integer. + * + */ + subscribeToBalance = async (subscriber) => { + if (!this.isValid()) { + return false; + } + + return this.subscriptions.add( + 'ASSET_BALANCE', + this.id, + subscriber, + ); + }; + + unsubscribeToBalance = async subscriber => this.subscriptions.remove( + 'ASSET_BALANCE', + this.id, + subscriber, + ); + + /** + * @function zkAsset.deposit + * @description Description: Deposit funds into zero-knowledge form - convert public ERC20 tokens into zero-knowledge AZTEC notes. + * + * @param {[Transaction]} transactions Transaction information which the user wants to have enacted. Each transaction object consists of: + * + * - *amount* (Integer): Number of public ERC20 tokens being converted into notes. + * + * - *to* (Address): Ethereum address to which the user is 'depositing' the zero-knowledge funds. + * The address will become the owner of the notes. + * + * - *numberOfOutputNotes* (Integer) (optional): Number of output notes to create. + * + * - *aztecAccountNotRequired* (Boolean) (optional): Not to enforce recipient to have an aztec account. + * Useful when depositing funds to a contract. + * + * @param {Object} options Optional parameters to be passed: + * + * - *numberOfOutputNotes* (Integer): Number of new notes for each transaction. + * Unless `numberOfOutputNotes` is defined in that transaction. + * Will use default value in sdk settings if undefined. + * + * - *userAccess* ([Address]): Addresses that have been granted view access to the note value. + * + * - *returnProof* (Boolean): Return the JoinSplit proof instead of sending it. + * + * - *sender* (Address): The proof sender. Available only when `returnProof` is true. + * + * - *publicOwner* (Address): The owner of ERC token. Available only when `returnProof` is true. + * + * @returns {Object} txSummary Transaction summary information containing: + * + * - *success* (Boolean): Describes whether the transaction was successful. + * + * - *outputNotes* ([Note]): Notes deposited into the recipient accounts. + * + * - *proof* (JoinSplitProof): Available when `returnProof` is set to true. + * + */ + deposit = async (transactions, { + numberOfOutputNotes, + userAccess = [], + returnProof, + sender, + publicOwner, + } = {}) => { + if (!this.linkedTokenAddress) { + throw new ApiError('zkAsset.private', { + fn: 'deposit', + }); + } + + const { + success, + outputNotes, + proofData, + } = await ConnectionService.query( + 'constructProof', + { + proofType: 'DEPOSIT_PROOF', + assetAddress: this.address, + transactions: parseInputTransactions(transactions), + numberOfOutputNotes: parseInputInteger(numberOfOutputNotes), + userAccess, + returnProof, + sender, + publicOwner, + }, + ); + + let proof; + if (proofData) { + proof = proofData + ? await recoverJoinSplitProof(proofData) + : null; + } + + return { + success, + outputNotes, + proof, + }; + }; + + /** + * + * @function zkAsset.withdraw + * @description Description: Withdraw zero-knowledge funds into public form - convert notes into public ERC20 tokens. + * + * @param {Integer} amount Units of value being withdrawn - will equal the number of ERC20 tokens the `to` address receives. + * + * @param {Object} options Optional arguments to be passed: + * + * - *to* (Address): Ethereum address to the ERC20 tokens should be sent, upon withdrawal. Will use current address if undefined. + * + * - *numberOfInputNotes* (Integer): Number of notes to be destroyed. + * The sdk will pick a random number of notes if undefined. + * + * - *inputNoteHashes* ([NoteHash]): Notes to be destroyed. + * Their total value should be larger than or equal to the total transaction amount + * if `numberOfInputNotes` is defined and is equal to the array size. + * Otherwise, the sdk will pick extra notes if necessary. + * + * - *returnProof* (Boolean): Return the JoinSplit proof instead of sending it. + * + * - *sender* (Address): The proof sender. Available only when `returnProof` is true. + * + * @returns {Object} txSummary Transaction summary information containing: + * + * - *success* (Boolean): Describes whether the transaction was successful. + * + * - *proof* (JoinSplitProof): Available when `returnProof` is set to true. + * + */ + withdraw = async (amount, { + to, + numberOfInputNotes, + inputNoteHashes, + returnProof, + sender, + } = {}) => { + if (!this.linkedTokenAddress) { + throw new ApiError('zkAsset.private', { + fn: 'withdraw', + }); + } + + const { + address, + } = Web3Service.account; + + const { + success, + proofData, + } = await ConnectionService.query( + 'constructProof', + { + proofType: 'WITHDRAW_PROOF', + assetAddress: this.address, + amount: parseInputInteger(amount), + to: to || address, + publicOwner: to || address, + numberOfInputNotes: parseInputInteger(numberOfInputNotes), + inputNoteHashes, + returnProof, + sender, + }, + ); + + let proof = null; + if (proofData) { + proof = proofData + ? await recoverJoinSplitProof(proofData) + : null; + } + + return { + success, + proof, + }; + }; + + /** + * + * @function zkAsset.send + * @description Description: Send funds confidentially to another Ethereum address. + * + * @param {[Transaction]} transactions Transaction information which the user wants to have enacted. Each transaction object consists of: + * + * - *amount* (Integer): Units of value to transfer, where 1 unit is equivalent in value to 1 ERC20 token. + * + * - *to* (Address): Ethereum address to which the user is sending zero-knowledge funds. + * + * - *numberOfOutputNotes* (Integer) (optional): Number of output notes of this transaction. + * + * - *aztecAccountNotRequired* (Boolean) (optional): Not to enforce recipient to have an aztec account. + * + * @param {Object} options Optional arguments to be passed: + * + * - *numberOfInputNotes* (Integer): Number of notes to be destroyed. + * The sdk will pick a random number of notes if undefined. + * + * - *numberOfOutputNotes* (Integer): Number of new notes for each transaction. + * Unless `numberOfOutputNotes` is defined in that transaction. + * Will use default value in sdk settings if undefined. + * + * - *inputNoteHashes* ([NoteHash]): Notes to be destroyed. + * Their total value should be larger than or equal to the total transaction amount + * if `numberOfInputNotes` is defined and is equal to the array size. + * Otherwise, the sdk will pick extra notes if necessary. + * + * - *userAccess* ([Address]): The addresses that are able to see the real note value. + * + * - *returnProof* (Boolean): Return the JoinSplit proof instead of sending it. + * + * - *sender* (Address): The proof sender. Available only when `returnProof` is true. + * + * - *publicOwner* (Address): The owner of ERC token. Available only when `returnProof` is true. + * + * @returns {Object} txSummary Transaction summary information containing: + * + * - *success* (Boolean): Describes whether the transaction was successful. + * + * - *outputNotes* ([Note]): Notes sent to the recipient accounts. + * + * - *proof* (JoinSplitProof): Available when `returnProof` is set to true. + * + */ + send = async (transactions, { + numberOfInputNotes, + numberOfOutputNotes, + inputNoteHashes, + userAccess, + returnProof, + sender, + publicOwner, + } = {}) => { + const { + success, + outputNotes, + proofData, + } = await ConnectionService.query( + 'constructProof', + { + proofType: 'TRANSFER_PROOF', + assetAddress: this.address, + transactions: parseInputTransactions(transactions), + numberOfInputNotes: parseInputInteger(numberOfInputNotes), + numberOfOutputNotes: parseInputInteger(numberOfOutputNotes), + inputNoteHashes, + userAccess, + returnProof, + sender, + publicOwner, + }, + ); + + let proof; + if (proofData) { + proof = proofData + ? await recoverJoinSplitProof(proofData) + : null; + } + + return { + success, + outputNotes, + proof, + }; + }; + + /** + * + * Swap + * + * - swap object containing the notes to be swapped + * makerBid Note Hash of the makers bid + * takerBid Note Hash of the takers bid + * takerAsk Note Hash of the takers ask + * makerAsk Note Hash of the makers ask + * + * - options + * sender (String): The proof sender. + * numberOfInputNotes (Int): Number of notes picked from esisting pool. + * Will use extension's or user's setting if undefined. + * numberOfOutputNotes (Int): Number of new notes for each transaction. + * Unless numberOfOutputNotes is defined in that transaction. + * + * @returns ([Notes!]) + */ + swap = async ( + // swap, + // { + // sender = '', + // } = {}, + ) => { + // TODO + }; + + + /** + * + * Mint + * This api is available only when the asset is ZkAssetMintable + * + * - transactions ([Transaction!]) Transaction = { amount, to, numberOfOutputNotes } + * - options + * sender (String): The proof sender. + * If empty, will use extension's current user. + * numberOfOutputNotes (Int): Number of new notes. + * If input amount is an array, this value will be ignored. + * + * @returns ([Notes!]) + */ + mint = async ( + // transactions, + // { + // sender = '', + // numberOfOutputNotes = 1, + // } = {}, + ) => { + if (!this.canAdjustSupply) { + throw new ApiError('api.mint.notValid'); + } + + // TODO + }; + + /** + * + * Burn + * This api is available only when the asset is ZkAssetBurnable + * + * - notes ([Note!] or [AztecNote!]) + * - options + * sender (String): The proof sender. + * If empty, will use extension's current user. + * numberOfOutputNotes (Int): Number of new notes. + * If input amount is an array, this value will be ignored. + * + * @returns ([Notes!]) + */ + burn = async ( + // notes, + // { + // sender = '', + // } = {}, + ) => { + if (!this.canAdjustSupply) { + throw new ApiError('api.burn.notValid'); + } + + // TODO + }; + + /** + * + * @function zkAsset.createNoteFromBalance + * @description Description: Manually create notes, with particular values drawn from the user's balance. + * + * @param {Integer} amount Total value of the notes to be created. + * + * @param {Object} options Optional arguments to be passed: + * + * - *userAccess* ([Address]): The addresses that are able to see the real value of the new notes. + * + * - *numberOfInputNotes* (Integer): Number of notes to be destroyed. + * The sdk will pick a random number of notes if undefined. + * + * - *numberOfOutputNotes* (Integer): Number of new notes to be created. Default value is 1. + * + * @returns {[Note]} notes An Array of notes that have been created, where each note object contains: + * + * - *noteHash* (String) + * + * - *value* (Integer) + * + */ + createNoteFromBalance = async (amount, { + userAccess = [], + numberOfInputNotes, + numberOfOutputNotes = 1, + } = {}) => { + const { + notes, + } = await ConnectionService.query( + 'constructProof', + { + proofType: 'CREATE_NOTE_FROM_BALANCE_PROOF', + assetAddress: this.address, + amount: parseInputInteger(amount), + userAccess, + numberOfInputNotes: parseInputInteger(numberOfInputNotes), + numberOfOutputNotes: parseInputInteger(numberOfOutputNotes), + }, + ) || {}; + + return notes; + }; + + /** + * + * @function zkAsset.fetchNotesFromBalance + * @description Description: Fetch the notes stored in the `zkAsset` that are owned by the user and match the given query. + * + * @param {Object} query Optional query object that can be used to refine the parameters of the note fetch. + * If not supplied, will return all the notes owned by the user. + * + * - *equalTo* (Integer): The exact value all notes need to match. + * + * - *greaterThan* (Integer): If no equalTo parameter, the minimum value of notes returned. + * + * - *lessThan* (Integer): If no equalTo parameter, the maximum value of notes returned. + * + * - *numberOfNotes* (Integer): Number of notes which match the query to return. + * + * @returns {[Note]} notes Fetched notes that satisfy the parameters of the fetch query. Each note is an object containing: + * + * - *noteHash* (String) + * + * - *value* (Integer) + * + */ + fetchNotesFromBalance = async ({ + greaterThan, + lessThan, + equalTo, + numberOfNotes, + } = {}) => ConnectionService.query( + 'fetchNotesFromBalance', + { + assetAddress: this.address, + greaterThan: parseInputInteger(greaterThan), + lessThan: parseInputInteger(lessThan), + equalTo: parseInputInteger(equalTo), + numberOfNotes: parseInputInteger(numberOfNotes), + }, + ); + + /** + * + * @function zkAsset.toNoteValue + * @description Description: Convert the ERC20 token value to its equivalent note value. + * + * @param {Integer|String|BigNumber} tokenValue Value of ERC20 token to be converted. + * + * @returns {Integer} noteValue Equivalent note value of `tokenValue`. + * + */ + toNoteValue = (tokenValue) => { + const { + decimals, + } = this.token || {}; + + return tokenToNoteValue({ + value: tokenValue, + scalingFactor: this.scalingFactor, + decimals: decimals || 0, + }); + }; + + /** + * + * @function zkAsset.toTokenValue + * @description Description: Convert note value to its equivalent ERC20 token value. + * + * @param {Integer|String|BigNumber} noteValue Value of note to be converted. + * + * @param {Boolean} format Optional parameter to format the output string. + * + * @returns {String} tokenValue Equivalent ERC20 token value of `noteValue`. + * + */ + toTokenValue = (noteValue, format = false) => { + const { + decimals, + } = this.token || {}; + + return noteToTokenValue({ + value: noteValue, + scalingFactor: this.scalingFactor, + decimals: decimals || 0, + format, + }); + }; +} diff --git a/packages/documentation/src/apis/ZkNote.js b/packages/documentation/src/apis/ZkNote.js new file mode 100644 index 000000000..4a480bcd9 --- /dev/null +++ b/packages/documentation/src/apis/ZkNote.js @@ -0,0 +1,284 @@ +import { + fromViewingKey, +} from '~/utils/note'; +import ConnectionService from '~/client/services/ConnectionService'; +import provePrivateRange from '~/client/apis/privateRange/prove'; + +const dataProperties = [ + 'noteHash', + 'value', + 'viewingKey', + 'owner', + 'asset', + 'status', +]; + +export default class ZkNote { + constructor({ + id, + ...note + } = {}) { + dataProperties.forEach((key) => { + this[key] = note[key]; + }); + this.id = id; + } + + get valid() { + return typeof this.value === 'number'; + } + + get visible() { + return !!this.viewingKey; + } + + get destroyed() { + return this.status === 'DESTROYED'; + } + + /** + * + * @function note.export + * @description Description: Export an aztec.js note instance for use in proofs. + * + * @returns {AztecNote} note An AZTEC note. + * + */ + async export() { + if (!this.visible) { + return null; + } + + const { + note, + } = await ConnectionService.query( + 'noteWithViewingKey', + { id: this.id }, + ) || {}; + + if (!note || !note.decryptedViewingKey) { + return null; + } + + const { + decryptedViewingKey, + owner = {}, + } = note; + + return fromViewingKey(decryptedViewingKey, owner.address); + } + + /** + * + * @function note.grantAccess + * @description Description: Grant note view access to an array of Ethereum addresses. + * + * @param {[Address]} addresses Array of Ethereum addresses that are to be granted note view access. + * + * @returns {Boolean} success Boolean describing whether the granting of view access was successfull. + * + */ + async grantAccess(addresses) { + if (!this.visible + || this.destroyed + ) { + return false; + } + + const addressList = typeof addresses === 'string' + ? [addresses] + : addresses; + + const { + success, + } = await ConnectionService.query( + 'grantNoteAccess', + { + id: this.id, + addresses: addressList, + }, + ) || {}; + + return success || false; + } + + /** + * + * @function note.equal + * @description Description: Construct a proof that the note is equal to a particular value. + * + * @param {ZkNote|AztecNote} comparisonNote Note that is being compared. + * + * @param {Object} options Optional parameters to be passed: + * + * - *sender* (Address): The proof sender. Will use current address if empty. + * + * - *remainderNote* (ZkNote|AztecNote): Helper note to make the equation hold. + * In this api, its value should be 0. + * The sdk will construct one if not provided. + * + * @returns {PrivateRangeProof} proof Instance of the constructed proof. + * + */ + async equal(comparisonNote, { + sender = '', + remainderNote = null, + } = {}) { + if (!this.visible) { + return false; + } + + const originalNote = await this.export(); + return provePrivateRange({ + type: 'eq', + originalNote, + comparisonNote, + remainderNote, + sender, + }); + } + + /** + * + * @function note.greaterThan + * @description Description: Construct a proof that the note is greater than a particular value. + * + * @param {ZkNote|AztecNote} comparisonNote Note that is being compared. + * + * @param {Object} options Optional parameters to be passed: + * + * - *sender* (Address): The proof sender. Will use current address if empty. + * + * - *remainderNote* (ZkNote|AztecNote): Helper note to make the equation hold. + * In this api, its value should be the value of the original zkNote minus the value of `comparisonNote`. + * The sdk will construct one if not provided. + * + * @returns {PrivateRangeProof} proof Instance of the constructed proof. + * + */ + async greaterThan(comparisonNote, { + sender = '', + remainderNote = null, + } = {}) { + if (!this.visible) { + return false; + } + + const originalNote = await this.export(); + return provePrivateRange({ + type: 'gt', + originalNote, + comparisonNote, + remainderNote, + sender, + }); + } + + /** + * + * @function note.lessThan + * @description Description: Construct a proof that the note value is less than a particular value. + * + * @param {ZkNote|AztecNote} comparisonNote Note that is being compared. + * + * @param {Object} options Optional parameters to be passed: + * + * - *sender* (Address): The proof sender. Will use current address if empty. + * + * - *remainderNote* (ZkNote|AztecNote): Helper note to make the equation hold. + * In this api, its value should be the value of `comparisonNote` minus the value of the original zkNote. + * The sdk will construct one if not provided. + * + * @returns {PrivateRangeProof} proof Instance of the constructed proof. + * + */ + async lessThan(comparisonNote, { + sender = '', + remainderNote = null, + } = {}) { + if (!this.visible) { + return false; + } + + const originalNote = await this.export(); + return provePrivateRange({ + type: 'lt', + originalNote, + comparisonNote, + remainderNote, + sender, + }); + } + + /** + * + * @function note.greaterThanOrEqualTo + * @description Description: Construct a proof that the note value is greater than or equal to a particular value. + * + * @param {ZkNote|AztecNote} comparisonNote Note that is being compared. + * + * @param {Object} options Optional parameters to be passed: + * + * - *sender* (Address): The proof sender. Will use current address if empty. + * + * - *remainderNote* (ZkNote|AztecNote): Helper note to make the equation hold. + * In this api, its value should be the value of the original zkNote minus the value of `comparisonNote`. + * The sdk will construct one if not provided. + * + * @returns {PrivateRangeProof} proof Instance of the constructed proof. + * + */ + async greaterThanOrEqualTo(comparisonNote, { + sender = '', + remainderNote = null, + } = {}) { + if (!this.visible) { + return false; + } + + const originalNote = await this.export(); + return provePrivateRange({ + type: 'gte', + originalNote, + comparisonNote, + remainderNote, + sender, + }); + } + + /** + * + * @function note.lessThanOrEqualTo + * @description Description: Construct a proof that the note value is less than or equal to a particular value. + * + * @param {ZkNote|AztecNote} comparisonNote Note that is being compared. + * + * @param {Object} options Optional parameters to be passed: + * + * - *sender* (Address): The proof sender. Will use current address if empty. + * + * - *remainderNote* (ZkNote|AztecNote): Helper note to make the equation hold. + * In this api, its value should be the value of `comparisonNote` minus the value of the original zkNote. + * The sdk will construct one if not provided. + * + * @returns {PrivateRangeProof} proof Instance of the constructed proof. + * + */ + async lessThanOrEqualTo(comparisonNote, { + sender = '', + remainderNote = null, + } = {}) { + if (!this.visible) { + return false; + } + + const originalNote = await this.export(); + return provePrivateRange({ + type: 'lte', + originalNote, + comparisonNote, + remainderNote, + sender, + }); + } +} diff --git a/packages/documentation/styleguide/categories/Examples/index.md b/packages/documentation/styleguide/categories/Examples/index.md index 50ca61df8..786509dd2 100644 --- a/packages/documentation/styleguide/categories/Examples/index.md +++ b/packages/documentation/styleguide/categories/Examples/index.md @@ -1,7 +1,6 @@ This section summaries the various starter kits, examples and demos of the Aztec protocol code. It is a good starting point for working with the protocol. -| Example | Description | Link | Last updated | | -| ------------------------- | ------------------------------------------------------ | ---------------------------------------------------------- | ------------ | --- | -| sdk-starter-kit | Starting point for building a dapp with the Aztec SDK | https://github.com/AztecProtocol/sdk-starter-kit | Feb 2020 | | -| loan-dapp-starter-kit | PoC confidential financial asset built with `aztec.js` | https://github.com/AztecProtocol/loan-dapp-starter-kit | March 2020 | | -| aztec-ganache-starter-kit | Demo of using `aztec.js` and the protocol on ganache | https://github.com/AztecProtocol/aztec-ganache-starter-kit | Feb 2020 | | +| Example | Description | Link | Last updated | | +| ------------------------- | ----------------------------------------------------- | ---------------------------------------------------------- | ------------ | --- | +| sdk-starter-kit | Starting point for building a dapp with the Aztec SDK | https://github.com/AztecProtocol/sdk-starter-kit | Feb 2020 | | +| aztec-ganache-starter-kit | Demo of using `aztec.js` and the protocol on ganache | https://github.com/AztecProtocol/aztec-ganache-starter-kit | Feb 2020 | | diff --git a/packages/documentation/styleguide/categories/Introduction/index.md b/packages/documentation/styleguide/categories/Introduction/index.md index 89c10ae90..86d169ebd 100644 --- a/packages/documentation/styleguide/categories/Introduction/index.md +++ b/packages/documentation/styleguide/categories/Introduction/index.md @@ -2,7 +2,7 @@ AZTEC is a privacy engine for Ethereum, enabling confidential transactions over This documentation site acts as a single source of information about the AZTEC protocol. It provides information about the: -- [`SDK`](/#/SDK): high level developer SDK for building Dapps +- [`SDK`](/#/SDK/The%20role%20of%20the%20SDK): high level developer SDK for building Dapps - [`aztec.js`](/#/aztec.js): low level JavaScript npm package, used for proof construction - [`Examples`](/#/Examples): starter kits, demos and code examples for getting started - [`Specification`](/#/Specification): technical protocol specification diff --git a/packages/documentation/styleguide/categories/Introduction/joinSplitProof.md b/packages/documentation/styleguide/categories/Introduction/joinSplitProof.md index 803888c6f..dca296949 100644 --- a/packages/documentation/styleguide/categories/Introduction/joinSplitProof.md +++ b/packages/documentation/styleguide/categories/Introduction/joinSplitProof.md @@ -7,7 +7,7 @@ In a `JoinSplit` proof particular notes are provided as inputs, and certain note Consider the below example as to how value can be transferred using a JoinSplit proof:   - +   Alice wishes to confidentially transfer Bob 75 zkDAI. She starts off with 2 notes whose value sum to 100 zkDAI, whilst Bob starts off with no notes and no zkDAI. diff --git a/packages/documentation/styleguide/categories/Introduction/standardFlow.md b/packages/documentation/styleguide/categories/Introduction/standardFlow.md index e294689bd..a760017c4 100644 --- a/packages/documentation/styleguide/categories/Introduction/standardFlow.md +++ b/packages/documentation/styleguide/categories/Introduction/standardFlow.md @@ -32,4 +32,4 @@ The below diagram gives an overview of how the key smart contract infrastructure     - + diff --git a/packages/documentation/styleguide/categories/Introduction/utxoModel.md b/packages/documentation/styleguide/categories/Introduction/utxoModel.md index 30972588e..5d0f9fc6d 100644 --- a/packages/documentation/styleguide/categories/Introduction/utxoModel.md +++ b/packages/documentation/styleguide/categories/Introduction/utxoModel.md @@ -3,4 +3,4 @@ AZTEC utilises a UTXO model like that of Bitcoin, where the UTXOs are called `no     - + diff --git a/packages/documentation/styleguide/components/SdkPlayground/index.jsx b/packages/documentation/styleguide/components/SdkPlayground/index.jsx index 1663c0b6c..ca2c7ba43 100644 --- a/packages/documentation/styleguide/components/SdkPlayground/index.jsx +++ b/packages/documentation/styleguide/components/SdkPlayground/index.jsx @@ -199,7 +199,7 @@ class SdkPlayground extends PureComponent { <>