Skip to content

Commit

Permalink
[chore] CreateTransferOptions type for createtransfer (#77)
Browse files Browse the repository at this point in the history
  • Loading branch information
John-peterson-coinbase authored Jun 21, 2024
1 parent 97f0fcd commit 460e725
Show file tree
Hide file tree
Showing 9 changed files with 148 additions and 129 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Coinbase Node.js SDK Changelog

## Pending

### Added

- `CreateTransferOptions` type

## [0.0.8] - 2024-06-18

### Added
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ console.log(`Faucet transaction: ${faucetTransaction}`);
// Create a new Wallet to transfer funds to.
// Then, we can transfer 0.00001 ETH out of the Wallet to another Wallet.
const anotherWallet = await user.createWallet();
const transfer = await wallet.createTransfer(0.00001, Coinbase.assets.Eth, anotherWallet);
const transfer = await wallet.createTransfer({ amount: 0.00001, assetId: Coinbase.assets.Eth, destination: anotherWallet });
```


Expand Down
25 changes: 13 additions & 12 deletions src/coinbase/address/wallet_address.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { ArgumentError, InternalError } from "../errors";
import { FaucetTransaction } from "../faucet_transaction";
import { Trade } from "../trade";
import { Transfer } from "../transfer";
import { Amount, Destination, TransferStatus } from "../types";
import { Amount, Destination, TransferStatus, CreateTransferOptions } from "../types";
import { delay } from "../utils";
import { Wallet as WalletClass } from "../wallet";

Expand Down Expand Up @@ -154,23 +154,24 @@ export class WalletAddress extends Address {
/**
* Transfers the given amount of the given Asset to the given address. Only same-Network Transfers are supported.
*
* @param amount - The amount of the Asset to send.
* @param assetId - The ID of the Asset to send. For Ether, Coinbase.assets.Eth, Coinbase.assets.Gwei, and Coinbase.assets.Wei supported.
* @param destination - The destination of the transfer. If a Wallet, sends to the Wallet's default address. If a String, interprets it as the address ID.
* @param intervalSeconds - The interval at which to poll the Network for Transfer status, in seconds.
* @param timeoutSeconds - The maximum amount of time to wait for the Transfer to complete, in seconds.
* @param options - The options to create the Transfer.
* @param options.amount - The amount of the Asset to send.
* @param options.assetId - The ID of the Asset to send. For Ether, Coinbase.assets.Eth, Coinbase.assets.Gwei, and Coinbase.assets.Wei supported.
* @param options.destination - The destination of the transfer. If a Wallet, sends to the Wallet's default address. If a String, interprets it as the address ID.
* @param options.timeoutSeconds - The maximum amount of time to wait for the Transfer to complete, in seconds.
* @param options.intervalSeconds - The interval at which to poll the Network for Transfer status, in seconds.
* @returns The transfer object.
* @throws {APIError} if the API request to create a Transfer fails.
* @throws {APIError} if the API request to broadcast a Transfer fails.
* @throws {Error} if the Transfer times out.
*/
public async createTransfer(
amount: Amount,
assetId: string,
destination: Destination,
intervalSeconds = 0.2,
public async createTransfer({
amount,
assetId,
destination,
timeoutSeconds = 10,
): Promise<Transfer> {
intervalSeconds = 0.2,
}: CreateTransferOptions): Promise<Transfer> {
if (!Coinbase.useServerSigner && !this.key) {
throw new InternalError("Cannot transfer from address without private key loaded");
}
Expand Down
13 changes: 12 additions & 1 deletion src/coinbase/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -561,8 +561,8 @@ export enum ServerSignerStatus {
*/
export type WalletCreateOptions = {
networkId?: string;
intervalSeconds?: number;
timeoutSeconds?: number;
intervalSeconds?: number;
};

/**
Expand Down Expand Up @@ -649,3 +649,14 @@ export enum StakeOptionsMode {
*/
PARTIAL = "partial",
}

/**
* Options for creating a Transfer.
*/
export type CreateTransferOptions = {
amount: Amount;
assetId: string;
destination: Destination;
timeoutSeconds?: number;
intervalSeconds?: number;
};
33 changes: 17 additions & 16 deletions src/coinbase/wallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@ import { ArgumentError, InternalError } from "./errors";
import { Transfer } from "./transfer";
import {
Amount,
Destination,
SeedData,
WalletData,
ServerSignerStatus,
WalletCreateOptions,
CreateTransferOptions,
} from "./types";
import { convertStringToHex, delay } from "./utils";
import { FaucetTransaction } from "./faucet_transaction";
Expand Down Expand Up @@ -81,8 +81,8 @@ export class Wallet {
*/
public static async create({
networkId = Coinbase.networks.BaseSepolia,
intervalSeconds = 0.2,
timeoutSeconds = 20,
intervalSeconds = 0.2,
}: WalletCreateOptions = {}): Promise<Wallet> {
const result = await Coinbase.apiClients.wallet!.createWallet({
wallet: {
Expand Down Expand Up @@ -582,33 +582,34 @@ export class Wallet {
* Transfers the given amount of the given Asset to the given address. Only same-Network Transfers are supported.
* Currently only the default_address is used to source the Transfer.
*
* @param amount - The amount of the Asset to send.
* @param assetId - The ID of the Asset to send.
* @param destination - The destination of the transfer. If a Wallet, sends to the Wallet's default address. If a String, interprets it as the address ID.
* @param intervalSeconds - The interval at which to poll the Network for Transfer status, in seconds.
* @param timeoutSeconds - The maximum amount of time to wait for the Transfer to complete, in seconds.
* @param options - The options to create the Transfer.
* @param options.amount - The amount of the Asset to send.
* @param options.assetId - The ID of the Asset to send.
* @param options.destination - The destination of the transfer. If a Wallet, sends to the Wallet's default address. If a String, interprets it as the address ID.
* @param options.timeoutSeconds - The maximum amount of time to wait for the Transfer to complete, in seconds.
* @param options.intervalSeconds - The interval at which to poll the Network for Transfer status, in seconds.
* @returns The hash of the Transfer transaction.
* @throws {APIError} if the API request to create a Transfer fails.
* @throws {APIError} if the API request to broadcast a Transfer fails.
* @throws {Error} if the Transfer times out.
*/
public async createTransfer(
amount: Amount,
assetId: string,
destination: Destination,
intervalSeconds = 0.2,
public async createTransfer({
amount,
assetId,
destination,
timeoutSeconds = 10,
): Promise<Transfer> {
intervalSeconds = 0.2,
}: CreateTransferOptions): Promise<Transfer> {
if (!this.getDefaultAddress()) {
throw new InternalError("Default address not found");
}
return await this.getDefaultAddress()!.createTransfer(
return await this.getDefaultAddress()!.createTransfer({
amount,
assetId,
destination,
intervalSeconds,
timeoutSeconds,
);
intervalSeconds,
});
}

/**
Expand Down
10 changes: 5 additions & 5 deletions src/tests/e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,11 +86,11 @@ describe("Coinbase SDK E2E Test", () => {
expect(unhydratedWallet.getId()).toBe(walletId);

console.log("Transfering 0.000000001 ETH from default address to second address...");
const transfer = await unhydratedWallet.createTransfer(
0.000000001,
Coinbase.assets.Eth,
wallet,
);
const transfer = await unhydratedWallet.createTransfer({
amount: 0.000000001,
assetId: Coinbase.assets.Eth,
destination: wallet,
});
expect(await transfer.getStatus()).toBe(TransferStatus.COMPLETE);
console.log(`Transferred 1 Gwei from ${unhydratedWallet} to ${wallet}`);

Expand Down
10 changes: 5 additions & 5 deletions src/tests/user_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -232,11 +232,11 @@ describe("User Class", () => {
);
await expect(unhydratedWallet.createAddress()).rejects.toThrow(InternalError);
await expect(
unhydratedWallet.createTransfer(
new Decimal("500000000000000000"),
Coinbase.assets.Eth,
address1,
),
unhydratedWallet.createTransfer({
amount: new Decimal("500000000000000000"),
assetId: Coinbase.assets.Eth,
destination: address1,
}),
).rejects.toThrow(InternalError);
expect(unhydratedWallet.canSign()).toBe(false);
});
Expand Down
98 changes: 49 additions & 49 deletions src/tests/wallet_address_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ describe("WalletAddress", () => {
);
});

describe(".createTransfer", () => {
describe("#createTransfer", () => {
let weiAmount, destination, intervalSeconds, timeoutSeconds;
let walletId, id;

Expand Down Expand Up @@ -243,13 +243,13 @@ describe("WalletAddress", () => {
status: TransferStatus.COMPLETE,
});

await address.createTransfer(
weiAmount,
Coinbase.assets.Wei,
await address.createTransfer({
amount: weiAmount,
assetId: Coinbase.assets.Wei,
destination,
intervalSeconds,
timeoutSeconds,
);
intervalSeconds,
});

expect(Coinbase.apiClients.transfer!.createTransfer).toHaveBeenCalledTimes(1);
expect(Coinbase.apiClients.transfer!.broadcastTransfer).toHaveBeenCalledTimes(1);
Expand All @@ -261,26 +261,26 @@ describe("WalletAddress", () => {
new APIError("Failed to create transfer"),
);
await expect(
address.createTransfer(
weiAmount,
Coinbase.assets.Wei,
address.createTransfer({
amount: weiAmount,
assetId: Coinbase.assets.Wei,
destination,
intervalSeconds,
timeoutSeconds,
),
intervalSeconds,
}),
).rejects.toThrow(APIError);
});

it("should throw an InternalError if the address key is not provided", async () => {
const addressWithoutKey = new WalletAddress(VALID_ADDRESS_MODEL, null!);
await expect(
addressWithoutKey.createTransfer(
weiAmount,
Coinbase.assets.Wei,
addressWithoutKey.createTransfer({
amount: weiAmount,
assetId: Coinbase.assets.Wei,
destination,
intervalSeconds,
timeoutSeconds,
),
intervalSeconds,
}),
).rejects.toThrow(InternalError);
});

Expand All @@ -302,13 +302,13 @@ describe("WalletAddress", () => {
networkId: Coinbase.networks.BaseMainnet,
});
await expect(
address.createTransfer(
weiAmount,
Coinbase.assets.Wei,
invalidDestination,
intervalSeconds,
address.createTransfer({
amount: weiAmount,
assetId: Coinbase.assets.Wei,
destination: invalidDestination,
timeoutSeconds,
),
intervalSeconds,
}),
).rejects.toThrow(ArgumentError);
});

Expand All @@ -318,13 +318,13 @@ describe("WalletAddress", () => {
null!,
);
await expect(
address.createTransfer(
weiAmount,
Coinbase.assets.Wei,
invalidDestination,
intervalSeconds,
address.createTransfer({
amount: weiAmount,
assetId: Coinbase.assets.Wei,
destination: invalidDestination,
timeoutSeconds,
),
intervalSeconds,
}),
).rejects.toThrow(ArgumentError);
});

Expand All @@ -334,13 +334,13 @@ describe("WalletAddress", () => {
new APIError("Failed to broadcast transfer"),
);
await expect(
address.createTransfer(
weiAmount,
Coinbase.assets.Wei,
address.createTransfer({
amount: weiAmount,
assetId: Coinbase.assets.Wei,
destination,
intervalSeconds,
timeoutSeconds,
),
intervalSeconds,
}),
).rejects.toThrow(APIError);
});

Expand All @@ -358,26 +358,26 @@ describe("WalletAddress", () => {
timeoutSeconds = 0.000002;

await expect(
address.createTransfer(
weiAmount,
Coinbase.assets.Wei,
address.createTransfer({
amount: weiAmount,
assetId: Coinbase.assets.Wei,
destination,
intervalSeconds,
timeoutSeconds,
),
intervalSeconds,
}),
).rejects.toThrow("Transfer timed out");
});

it("should throw an ArgumentError if there are insufficient funds", async () => {
const insufficientAmount = new Decimal("10000000000000000000");
await expect(
address.createTransfer(
insufficientAmount,
Coinbase.assets.Wei,
address.createTransfer({
amount: insufficientAmount,
assetId: Coinbase.assets.Wei,
destination,
intervalSeconds,
timeoutSeconds,
),
intervalSeconds,
}),
).rejects.toThrow(ArgumentError);
});

Expand All @@ -389,13 +389,13 @@ describe("WalletAddress", () => {
status: TransferStatus.COMPLETE,
});

await address.createTransfer(
weiAmount,
Coinbase.assets.Wei,
await address.createTransfer({
amount: weiAmount,
assetId: Coinbase.assets.Wei,
destination,
intervalSeconds,
timeoutSeconds,
);
intervalSeconds,
});

expect(Coinbase.apiClients.transfer!.createTransfer).toHaveBeenCalledTimes(1);
expect(Coinbase.apiClients.transfer!.getTransfer).toHaveBeenCalledTimes(1);
Expand All @@ -406,7 +406,7 @@ describe("WalletAddress", () => {
});
});

describe(".getTransfers", () => {
describe("#getTransfers", () => {
beforeEach(() => {
jest.clearAllMocks();
const pages = ["abc", "def"];
Expand Down
Loading

0 comments on commit 460e725

Please sign in to comment.