Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: use credit sharing in commands/methods/docs PE-6754 #198

Merged
merged 8 commits into from
Nov 1, 2024
100 changes: 64 additions & 36 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,9 @@ Welcome to the `@ardrive/turbo-sdk`! This SDK provides functionality for interac
- [Polygon (POL / MATIC) Crypto Top Up](#polygon-pol--matic-crypto-top-up)
- [Solana (SOL) Crypto Top Up](#solana-sol-crypto-top-up)
- [KYVE Crypto Top Up](#kyve-crypto-top-up)
- [`createDelegatedPaymentApproval({ approvedAddress, approvedWincAmount, expiresBySeconds })`](#createdelegatedpaymentapproval-approvedaddress-approvedwincamount-expiresbyseconds-)
- [`revokeDelegatedPaymentApprovals({ approvedAddress })`](#revokedelegatedpaymentapprovals-approvedaddress-)
- [`getDelegatedPaymentApprovals({ userAddress })`](#getdelegatedpaymentapprovals-useraddress-)
- [`shareCredits({ approvedAddress, approvedWincAmount, expiresBySeconds })`](#sharecredits-approvedaddress-approvedwincamount-expiresbyseconds-)
- [`revokeCredits({ approvedAddress })`](#revokecredits-approvedaddress-)
- [`getCreditShareApprovals({ userAddress })`](#getcreditshareapprovals-useraddress-)
- [CLI](#cli)
- [Install CLI](#install-cli)
- [CLI Usage](#cli-usage)
Expand All @@ -79,9 +79,10 @@ Welcome to the `@ardrive/turbo-sdk`! This SDK provides functionality for interac
- [`upload-folder`](#upload-folder)
- [`upload-file`](#upload-file)
- [`price`](#price)
- [`create-approval`](#create-approval)
- [`revoke-approvals`](#revoke-approvals)
- [`list-approvals`](#list-approvals)
- [`share-credits`](#share-credits)
- [`revoke-credits`](#revoke-credits)
- [`list-shares`](#list-shares)
- [Turbo Credit Sharing](#turbo-credit-sharing)
- [Developers](#developers)
- [Requirements](#requirements)
- [Setup & Build](#setup--build)
Expand Down Expand Up @@ -683,36 +684,35 @@ const { winc, status, id, ...fundResult } = await turbo.topUpWithTokens({
});
```

#### `createDelegatedPaymentApproval({ approvedAddress, approvedWincAmount, expiresBySeconds })`
#### `shareCredits({ approvedAddress, approvedWincAmount, expiresBySeconds })`

Creates a delegated payment approval from the connected wallet to the provided native address and approved winc amount. This action will create a data item for the approval
Shares credits from the connected wallet to the provided native address and approved winc amount. This action will create a signed data item for the approval

```typescript
const { approvalDataItemId, approvedWincAmount } =
await turbo.createDelegatedPaymentApproval({
approvedAddress: '2cor...VUa',
approvedWincAmount: 0.08315565032,
expiresBySeconds: 3600,
});
const { approvalDataItemId, approvedWincAmount } = await turbo.shareCredits({
approvedAddress: '2cor...VUa',
approvedWincAmount: 0.08315565032,
expiresBySeconds: 3600,
});
```

#### `revokeDelegatedPaymentApprovals({ approvedAddress })`
#### `revokeCredits({ approvedAddress })`

Revokes all delegated payment approvals from the connected wallet to the provided native address.
Revokes all credits shared from the connected wallet to the provided native address.

```typescript
const revokedApprovals = await turbo.revokeDelegatePaymentApprovals({
const revokedApprovals = await turbo.revokeCredits({
approvedAddress: '2cor...VUa',
});
```

#### `getDelegatedPaymentApprovals({ userAddress })`
#### `getCreditShareApprovals({ userAddress })`

Returns all delegated payment approvals from the connected wallet or the provided native address.
Returns all given or received credit share approvals for the connected wallet or the provided native address.

```typescript
const { givenApprovals, receivedApprovals } =
await turbo.getDelegatedPaymentApprovals({
await turbo.getCreditShareApprovals({
userAddress: '2cor...VUa',
});
```
Expand Down Expand Up @@ -782,8 +782,8 @@ Wallet options:
Upload options:

- `--paid-by <paidBy...>` - A list of native addresses to pay for the upload.
- `--ignore-approvals` - When no paid by is provided, the CLI will look for and use any received delegated payment approvals to pay for the upload. This flag will ignore any approvals and only use the connected wallet's balance for upload payment. Default: false
- `--use-signer-balance-first` - Use the connected wallet's balance before using any delegated payment approvals for the upload. Default: false
- `--ignore-approvals` - When no paid by is provided, the CLI will look for and use any received credit share approvals to pay for the upload. This flag will ignore any approvals and only use the connected wallet's balance for upload payment. Default: false
- `--use-signer-balance-first` - Use the connected wallet's balance before using any credit share approvals for the upload. Default: false

#### Commands

Expand Down Expand Up @@ -896,50 +896,78 @@ turbo price --value 1024 --type bytes
turbo price --value 1.1 --type arweave
```

##### `create-approval`
##### `share-credits`

Create a delegated payment approval from the connected wallet to the provided native address and approved winc amount.
Shares credits from the connected wallet to the provided native address and approved winc amount.

Command Options:

- `-a, --address <nativeAddress>` - Native address to that will receive the delegated payment approval
- `-v, --value <value>` - Value of winc to create delegated payment approval for
- `-e, --expires-by-seconds <seconds>` - Expiry time in seconds for the delegated payment approval
- `-a, --address <nativeAddress>` - Native address to that will receive the Credits
- `-v, --value <value>` - Value of winc to share to the target address
- `-e, --expires-by-seconds <seconds>` - Expiry time in seconds for the credit share approval

e.g:

```shell
turbo create-approval --address 2cor...VUa --value 0.083155650320 --wallet-file ../path/to/my/wallet --expires-by-seconds 3600
turbo share-credits --address 2cor...VUa --value 0.083155650320 --wallet-file ../path/to/my/wallet --expires-by-seconds 3600
```

##### `revoke-approvals`
##### `revoke-credits`

Revoke all delegated payment approvals from the connected wallet to the provided native address.
Revoke all credits shared from the connected wallet to the provided native address.

Command Options:

- `-a, --address <nativeAddress>` - Native address to revoke delegated payment approvals for
- `-a, --address <nativeAddress>` - Native address to revoke credit share approvals for

e.g:

```shell
turbo revoke-approvals --wallet-file ../path/to/my/wallet
turbo revoke-credits --wallet-file ../path/to/my/wallet
```

##### `list-approvals`
##### `list-shares`

List all given and received delegated payment approvals from the connected wallet or the provided native address.
List all given and received credit share approvals from the connected wallet or the provided native address.

Command Options:

- `-a, --address <nativeAddress>` - Native address to list delegated payment approvals for
- `-a, --address <nativeAddress>` - Native address to list credit share approvals for

e.g:

```shell
turbo list-approvals --address 2cor...VUa --wallet-file ../path/to/my/wallet
turbo list-shares --address 2cor...VUa --wallet-file ../path/to/my/wallet
```

## Turbo Credit Sharing

Users can share their purchased Credits with other user's wallets by creating Credit Share Approvals. These approvals are created by uploading a signed data item with tags indicating the recipient's wallet address, the amount of Credits to share, and an optional amount of seconds that the approval will expire in. The recipient can then use the shared Credits to pay for their own uploads to Turbo.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

other user's wallets -> other users' wallets


Shared Credits cannot be re-shared by the recipient to other recipients. Only the owner of the Credits can share or revoke Credit Share Approvals. Credits that are shared to other wallets may not be used by the original owner of the Credits for sharing or uploading unless the Credit Share Approval is revoked or expired.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only the owner -> Only the original owner


Approvals can be revoked at any time by similarly uploading a signed data item with tags indicating the recipient's wallet address. This will remove all approvals and prevent the recipient from using the shared Credits. All unused Credits from expired or revoked approvals are returned to the original owner of the Credits.

To use the shared Credits, recipient users must provide the wallet address of the user who shared the Credits with them in the `x-paid-by` HTTP header when uploading data. This tells Turbo services to look for and use Credit Share Approvals to pay for the upload before using the signer's balance.

For user convenience, during upload the Turbo CLI will use any available Credit Share Approvals found for the connected wallet before using the signing wallet's balance. To instead ignore all Credit shares and only use the signer's balance, use the `--ignore-approvals` flag. To use the signer's balance first before using Credit shares, use the `--use-signer-balance-first` flag. The Turbo SDK layer does not provide this functionality and will always use the signer's balance unless `paidBy` is provided.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Turbo SDK layer does not provide this functionality and will always use the signer's balance unless paidBy is provided.
This is a little confusing... are you saying it can do it (and what is "it" specifically?") or not?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

specifically it does not provide any convenience of fetching approvals. it only uses the paidBy. I'll change up the wording

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

-> In contrast, the Turbo SDK layer does not provide this functionality and and will only use approvals when paidBy is provided.


The Turbo SDK provides the following methods to manage Credit Share Approvals:

- `shareCredits`: Creates a Credit Share Approval for the specified wallet address and amount of Credits.
- `revokeCredits`: Revokes all Credit Share Approvals for the specified wallet address.
- `listShares`: Lists all Credit Share Approvals for the specified wallet address or connected wallet.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we have no APIs that can list ALL of the credit share approvals provided by the original credit holder?

Copy link
Collaborator Author

@fedellen fedellen Nov 4, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if you mean approvals from single payer to a single signer, no not on the SDK level. the payment API does provide this for compatibility with the getApproval from ARx tooling. but this can be achieved by using the SDK and a simple filter: listShares(signerAddress).receivedApprovals.filter(a => a === payerAddress)

- `dataItemOpts: { ...opts, paidBy: string[] }`: Upload methods now accept an array of wallet addresses to pay for the upload.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Upload methods now accept an array of wallet addresses to pay for the upload. -> Upload methods now accept 'paidBy', an array of wallet addresses that have provided credit share approvals to the user from which to pay, in the order provided and as necessary, for the upload.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Kind of a mouthful, but perhaps GPT can clean it up


The Turbo CLI provides the following commands to manage Credit Share Approvals:

- `share-credits`: Creates a Credit Share Approval for the specified wallet address and amount of Credits.
- `revoke-credits`: Revokes all Credit Share Approvals for the specified wallet address.
- `list-shares`: Lists all Credit Share Approvals for the specified wallet address or connected wallet.
- `paidBy: --paid-by <paidBy...>`: Upload commands now accept an array of wallet addresses to pay for the upload.
- `--ignore-approvals`: Ignore all Credit Share Approvals and only use the signer's balance.
- `--use-signer-balance-first`: Use the signer's balance first before using Credit Share Approvals.

## Developers

### Requirements
Expand Down
38 changes: 18 additions & 20 deletions src/cli/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
import { Command, program } from 'commander';

import { version } from '../version.js';
import { createApproval } from './commands/createApproval.js';
import {
balance,
cryptoFund,
Expand All @@ -29,14 +28,15 @@ import {
uploadFile,
uploadFolder,
} from './commands/index.js';
import { listApprovals } from './commands/listApprovals.js';
import { revokeApprovals } from './commands/revokeApprovals.js';
import { listShares } from './commands/listShares.js';
import { revokeCredits } from './commands/revokeCredits.js';
import { shareCredits } from './commands/shareCredits.js';
import {
createApprovalOptions,
globalOptions,
listApprovalsOptions,
listSharesOptions,
optionMap,
revokeApprovalsOptions,
revokeCreditsOptions,
shareCreditsOptions,
uploadFileOptions,
uploadFolderOptions,
walletOptions,
Expand Down Expand Up @@ -101,33 +101,31 @@ applyOptions(

applyOptions(
program
.command('create-approval')
.description('Create a Turbo delegated payment approval'),
createApprovalOptions,
.command('share-credits')
.description('Create a Turbo credit share approval'),
shareCreditsOptions,
).action(async (_commandOptions, command: Command) => {
await runCommand(command, createApproval);
await runCommand(command, shareCredits);
});

applyOptions(
program
.command('revoke-approvals')
.description(
'Revokes all Turbo delegated payment approvals for given address',
),
revokeApprovalsOptions,
.command('revoke-credits')
.description('Revokes all Turbo credit share approvals for given address'),
revokeCreditsOptions,
).action(async (_commandOptions, command: Command) => {
await runCommand(command, revokeApprovals);
await runCommand(command, revokeCredits);
});

applyOptions(
program
.command('list-approvals')
.command('list-shares')
.description(
'Lists all Turbo delegated payment approvals for given address or wallet',
'Lists all given or received Turbo credit share approvals for specified address or connected wallet',
),
listApprovalsOptions,
listSharesOptions,
).action(async (_commandOptions, command: Command) => {
await runCommand(command, listApprovals);
await runCommand(command, listShares);
});

if (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,10 @@
* limitations under the License.
*/
import { TurboFactory } from '../../node/factory.js';
import { ListApprovalsOptions } from '../types.js';
import { ListSharesOptions } from '../types.js';
import { addressOrPrivateKeyFromOptions, configFromOptions } from '../utils.js';

export async function listApprovals(
options: ListApprovalsOptions,
): Promise<void> {
export async function listShares(options: ListSharesOptions): Promise<void> {
const config = configFromOptions(options);
const { address, privateKey } = await addressOrPrivateKeyFromOptions(options);

Expand All @@ -28,7 +26,7 @@ export async function listApprovals(
if (address !== undefined) {
const approvals = await TurboFactory.unauthenticated(
config,
).getDelegatedPaymentApprovals({
).getCreditShareApprovals({
userAddress: address,
});
return { ...approvals, nativeAddress: address };
Expand All @@ -40,7 +38,7 @@ export async function listApprovals(
...config,
privateKey,
});
const approvals = await turbo.getDelegatedPaymentApprovals();
const approvals = await turbo.getCreditShareApprovals();
return {
...approvals,
nativeAddress: await turbo.signer.getNativeAddress(),
Expand All @@ -51,8 +49,8 @@ export async function listApprovals(
givenApprovals?.length === 0 && receivedApprovals?.length === 0;
const body = {
message:
`${hasApprovals ? 'No d' : 'D'}` +
`elegated payment approvals found for native address '${nativeAddress}'`,
`${hasApprovals ? 'No ' : ''}` +
`Credit Share Approvals found for native address '${nativeAddress}'`,
givenApprovals,
receivedApprovals,
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { RevokeApprovalsOptions } from '../types.js';
import { RevokeCreditsOptions } from '../types.js';
import { turboFromOptions } from '../utils.js';

export async function revokeApprovals(
options: RevokeApprovalsOptions,
export async function revokeCredits(
options: RevokeCreditsOptions,
): Promise<void> {
const { address: revokedAddress } = options;
if (revokedAddress === undefined) {
Expand All @@ -28,13 +28,13 @@ export async function revokeApprovals(

const turbo = await turboFromOptions(options);

const revokedApprovals = await turbo.revokeDelegatedPaymentApprovals({
const revokedApprovals = await turbo.revokeCredits({
revokedAddress,
});

console.log(
JSON.stringify(
{ message: 'Revoked delegated payment approvals!', revokedApprovals },
{ message: 'Revoked credit share approvals!', revokedApprovals },
null,
2,
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@
*/
import { BigNumber } from 'bignumber.js';

import { CreateApprovalOptions } from '../types.js';
import { ShareCreditsOptions } from '../types.js';
import { turboFromOptions } from '../utils.js';

export async function createApproval(
options: CreateApprovalOptions,
export async function shareCredits(
options: ShareCreditsOptions,
): Promise<void> {
const {
address: approvedAddress,
Expand All @@ -40,15 +40,15 @@ export async function createApproval(
const approvedWincAmount = new BigNumber(creditAmount)
.shiftedBy(12)
.toFixed(0);
const result = await turbo.createDelegatedPaymentApproval({
const result = await turbo.shareCredits({
approvedAddress,
approvedWincAmount,
expiresBySeconds,
});

console.log(
JSON.stringify(
{ message: 'Created delegated payment approval!', ...result },
{ message: 'Created credit share approval!', ...result },
null,
2,
),
Expand Down
10 changes: 5 additions & 5 deletions src/cli/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,13 +137,13 @@ export const optionMap = {
ignoreApprovals: {
alias: '--ignore-approvals',
description:
"Ignore all delegated payment approvals, only use signing wallet's balance",
"Ignore all credit share approvals, only use signing wallet's balance",
default: false,
},
useSignerBalanceFirst: {
alias: '--use-signer-balance-first',
description:
'Use the signer balance first before using delegated payment approvals',
'Use the signer balance first before using credit share approvals',
default: false,
},
} as const;
Expand Down Expand Up @@ -184,13 +184,13 @@ export const uploadFolderOptions = [

export const uploadFileOptions = [...uploadOptions, optionMap.filePath];

export const createApprovalOptions = [
export const shareCreditsOptions = [
...walletOptions,
optionMap.value,
optionMap.address,
optionMap.expiresBySeconds,
];

export const revokeApprovalsOptions = [...walletOptions, optionMap.address];
export const revokeCreditsOptions = [...walletOptions, optionMap.address];

export const listApprovalsOptions = revokeApprovalsOptions;
export const listSharesOptions = revokeCreditsOptions;
Loading
Loading