diff --git a/src/cli/cli.ts b/src/cli/cli.ts index 8df93bdd..9181e185 100644 --- a/src/cli/cli.ts +++ b/src/cli/cli.ts @@ -29,10 +29,12 @@ import { uploadFile, uploadFolder, } from './commands/index.js'; +import { listApprovals } from './commands/listApprovals.js'; import { revokeApprovals } from './commands/revokeApprovals.js'; import { createApprovalOptions, globalOptions, + listApprovalsOptions, optionMap, revokeApprovalsOptions, uploadFileOptions, @@ -116,6 +118,17 @@ applyOptions( await runCommand(command, revokeApprovals); }); +applyOptions( + program + .command('list-approvals') + .description( + 'Lists all Turbo delegated payment approvals for given address or wallet', + ), + listApprovalsOptions, +).action(async (_commandOptions, command: Command) => { + await runCommand(command, listApprovals); +}); + if ( process.argv[1].includes('bin/turbo') || // Running from global .bin process.argv[1].includes('cli/cli') // Running from source diff --git a/src/cli/commands/balance.ts b/src/cli/commands/balance.ts index b814e968..58dce8b3 100644 --- a/src/cli/commands/balance.ts +++ b/src/cli/commands/balance.ts @@ -13,7 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +import { BigNumber } from 'bignumber.js'; + import { TurboFactory } from '../../node/factory.js'; +import { wincPerCredit } from '../constants.js'; import { AddressOptions } from '../types.js'; import { addressOrPrivateKeyFromOptions, configFromOptions } from '../utils.js'; @@ -21,7 +24,7 @@ export async function balance(options: AddressOptions) { const config = configFromOptions(options); const { address, privateKey } = await addressOrPrivateKeyFromOptions(options); - const { winc, givenApprovals, receivedApprovals, nativeAddress } = + const { effectiveBalance, nativeAddress, winc, controlledWinc } = await (async () => { if (address !== undefined) { return { @@ -43,16 +46,14 @@ export async function balance(options: AddressOptions) { })(); console.log( - `Turbo Balance for Native Address "${nativeAddress}"\nCredits: ${ - +winc / 1_000_000_000_000 - }${ - givenApprovals?.length > 0 - ? `\nGiven Approvals:\n${JSON.stringify(givenApprovals, null, 2)}` - : '' + `Turbo Balance for Native Address "${nativeAddress}"\nEffective Credits: ${ + +effectiveBalance / wincPerCredit }${ - receivedApprovals?.length > 0 - ? `\nReceived Approvals:\n${JSON.stringify(receivedApprovals, null, 2)}` - : '' + winc === controlledWinc + ? '' + : `\nCredits Shared to Other Wallets: ${BigNumber(controlledWinc) + .minus(winc) + .div(wincPerCredit)}` }`, ); } diff --git a/src/cli/commands/createApproval.ts b/src/cli/commands/createApproval.ts index d00c1bd0..9c3ffb7e 100644 --- a/src/cli/commands/createApproval.ts +++ b/src/cli/commands/createApproval.ts @@ -46,5 +46,7 @@ export async function createApproval( expiresBySeconds, }); - console.log('Created approval:', JSON.stringify(result, null, 2)); + console.log( + JSON.stringify({ message: 'Created approval:', ...result }, null, 2), + ); } diff --git a/src/cli/commands/cryptoFund.ts b/src/cli/commands/cryptoFund.ts index 46a61148..43adece0 100644 --- a/src/cli/commands/cryptoFund.ts +++ b/src/cli/commands/cryptoFund.ts @@ -17,6 +17,7 @@ import prompts from 'prompts'; import { tokenToBaseMap } from '../../common/index.js'; import { TurboFactory } from '../../node/factory.js'; +import { wincPerCredit } from '../constants.js'; import { CryptoFundOptions } from '../types.js'; import { configFromOptions, @@ -54,7 +55,7 @@ export async function cryptoFund(options: CryptoFundOptions) { const { winc } = await turbo.getWincForToken({ tokenAmount }); const targetWallet = (await turbo.getTurboCryptoWallets())[token]; - const credits = (+winc / 1_000_000_000_000).toFixed(12); + const credits = (+winc / wincPerCredit).toFixed(12); const { confirm } = await prompts({ type: 'confirm', diff --git a/src/cli/commands/listApprovals.ts b/src/cli/commands/listApprovals.ts new file mode 100644 index 00000000..b2b4adbe --- /dev/null +++ b/src/cli/commands/listApprovals.ts @@ -0,0 +1,67 @@ +/** + * Copyright (C) 2022-2024 Permanent Data Solutions, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { TurboFactory } from '../../node/factory.js'; +import { ListApprovalsOptions } from '../types.js'; +import { addressOrPrivateKeyFromOptions, configFromOptions } from '../utils.js'; + +export async function listApprovals( + options: ListApprovalsOptions, +): Promise { + const config = configFromOptions(options); + const { address, privateKey } = await addressOrPrivateKeyFromOptions(options); + + const { givenApprovals, receivedApprovals, nativeAddress } = + await (async () => { + if (address !== undefined) { + const approvals = await TurboFactory.unauthenticated( + config, + ).getDelegatedPaymentApprovals({ + userAddress: address, + }); + return { ...approvals, nativeAddress: address }; + } + if (privateKey === undefined) { + throw new Error('Must provide an (--address) or use a valid wallet'); + } + const turbo = TurboFactory.authenticated({ + ...config, + privateKey, + }); + const approvals = await turbo.getDelegatedPaymentApprovals(); + return { + ...approvals, + nativeAddress: await turbo.signer.getNativeAddress(), + }; + })(); + + const hasApprovals = + givenApprovals?.length === 0 && receivedApprovals?.length === 0; + const body = { + message: + `${hasApprovals ? 'No approvals found ' : 'Approvals found'}` + + ` for native address '${nativeAddress}'`, + givenApprovals, + receivedApprovals, + }; + + if (givenApprovals?.length > 0) { + body['givenApprovals'] = givenApprovals; + } + if (receivedApprovals?.length > 0) { + body['receivedApprovals'] = receivedApprovals; + } + console.log(JSON.stringify(body, null, 2)); +} diff --git a/src/cli/commands/price.ts b/src/cli/commands/price.ts index b7710c6f..0651f674 100644 --- a/src/cli/commands/price.ts +++ b/src/cli/commands/price.ts @@ -17,6 +17,7 @@ import { currencyMap } from '../../common/currency.js'; import { isTokenType, tokenToBaseMap } from '../../common/index.js'; import { TurboFactory } from '../../node/factory.js'; import { fiatCurrencyTypes, isCurrency, tokenTypes } from '../../types.js'; +import { wincPerCredit } from '../constants.js'; import { PriceOptions } from '../types.js'; import { configFromOptions } from '../utils.js'; @@ -63,7 +64,7 @@ export async function price(options: PriceOptions) { console.log( `Current price estimate for ${value} ${type} is ~${( - +winc / 1_000_000_000_000 + +winc / wincPerCredit ).toFixed(12)} Credits`, ); } diff --git a/src/cli/commands/revokeApprovals.ts b/src/cli/commands/revokeApprovals.ts index 1c0fe981..1c965430 100644 --- a/src/cli/commands/revokeApprovals.ts +++ b/src/cli/commands/revokeApprovals.ts @@ -22,7 +22,7 @@ export async function revokeApprovals( const { address: revokedAddress } = options; if (revokedAddress === undefined) { throw new Error( - 'Must provide an approved --address to create approval for', + 'Must provide an approved --address to revoke approvals for', ); } @@ -32,5 +32,7 @@ export async function revokeApprovals( revokedAddress, }); - console.log('Created approval:', JSON.stringify(result, null, 2)); + console.log( + JSON.stringify({ message: 'Revoked approvals', ...result }, null, 2), + ); } diff --git a/src/cli/constants.ts b/src/cli/constants.ts index 56e7f56f..940abc3a 100644 --- a/src/cli/constants.ts +++ b/src/cli/constants.ts @@ -20,3 +20,5 @@ export const turboCliTags: { name: string; value: string }[] = [ { name: 'App-Version', value: version }, { name: 'App-Platform', value: process.platform }, ]; + +export const wincPerCredit = 1_000_000_000_000; diff --git a/src/cli/options.ts b/src/cli/options.ts index c543cc85..7b82b7cd 100644 --- a/src/cli/options.ts +++ b/src/cli/options.ts @@ -192,3 +192,5 @@ export const createApprovalOptions = [ ]; export const revokeApprovalsOptions = [...walletOptions, optionMap.address]; + +export const listApprovalsOptions = revokeApprovalsOptions; diff --git a/src/cli/types.ts b/src/cli/types.ts index 2e0a9ee4..4123b477 100644 --- a/src/cli/types.ts +++ b/src/cli/types.ts @@ -78,3 +78,5 @@ export type CreateApprovalOptions = WalletOptions & { export type RevokeApprovalsOptions = WalletOptions & { address: string | undefined; }; + +export type ListApprovalsOptions = RevokeApprovalsOptions;