Skip to content

Commit

Permalink
Enable wallet activity events support for webhooks at wallet level (#245
Browse files Browse the repository at this point in the history
)

* add eventTypeFilter

* Update types.ts

* Update webhook_test.ts

* Update webhook.ts

* Update webhook_test.ts

* Update webhook.ts

* Update webhook_test.ts

* Update webhook_test.ts

* Update webhook_test.ts

* Update webhook_test.ts

* Update webhook_test.ts

* wallet.create_webhook

* Changelog

* Update wallet.ts

* Update wallet.ts

* Update wallet_test.ts

* Update wallet_test.ts

* Update wallet_test.ts

* Update wallet_test.ts

* Update wallet_test.ts

* fmt

* Update wallet_test.ts

* Update wallet_test.ts

* Update webhook.ts

* Update wallet_test.ts

* Update wallet_test.ts

* address comments

* fix test

* Update wallet_test.ts

* Update wallet_test.ts

* Update wallet_test.ts

* Update wallet_test.ts

* Update jest.config.js

* add sol, lamport asset suppport

* Fix Asset toAtomicAmount to not return scientific notation (#250)

* Fix merge conflicts between master and v0.6.0 (#255)

* fix arb

* update version

* remove network check logic from sdk

* fix coverage

* fix lint

* [PSDK-443] Quickstart Basenames Registration (#243)

* base names quickstart

* [PSDK-443] Quickstart Register Basenames for MPC Wallet

* [hotfix] Fix L2 Resolver Address on Register Basenames Quickstart (#244)

---------

Co-authored-by: Jayasudha Jayakumaran <jayasudha.jayakumaran@coinbase.com>
Co-authored-by: Jayasudha Jayakumaran <121061531+jazz-cb@users.noreply.github.com>
Co-authored-by: John Peterson <98187317+John-peterson-coinbase@users.noreply.github.com>

* address comments

* Update api.ts

* Update CHANGELOG.md

* apply new changes

* fix tests

* Update wallet.ts

* Update CHANGELOG.md

* Update CHANGELOG.md

* Update jest.config.js

---------

Co-authored-by: Rohan Agarwal <rohan.agarwal.1@coinbase.com>
Co-authored-by: Rohit Durvasula <rohit.durvasula@coinbase.com>
Co-authored-by: Jayasudha Jayakumaran <jayasudha.jayakumaran@coinbase.com>
Co-authored-by: Jayasudha Jayakumaran <121061531+jazz-cb@users.noreply.github.com>
Co-authored-by: John Peterson <98187317+John-peterson-coinbase@users.noreply.github.com>
  • Loading branch information
6 people authored Sep 25, 2024
1 parent 923eaf8 commit a9a9864
Show file tree
Hide file tree
Showing 8 changed files with 253 additions and 19 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@

## Unreleased

## [0.7.0] - 2024-09-24
### Added
- Add `deployNFT` method to `WalletAddress` and `Wallet` to deploy an ERC721, updated `SmartContract` class to support deployment and fetching contract details
- Add `deployMultiToken` method to `WalletAddress` and `Wallet` to deploy an ERC1155, updated `SmartContract` class to support deployment and fetching contract details
- Add `createWebhook` method to `Wallet` to deploy a wallet activity webhook, updated `Webhook` class to disallow users from specifying webhook signature. Webhook signature is now generated by the API.

## [0.6.1] - 2024-09-23

Expand Down
4 changes: 2 additions & 2 deletions jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ module.exports = {
coverageThreshold: {
"./src/coinbase/**": {
branches: 77,
functions: 90,
functions: 85,
statements: 85,
lines: 87,
lines: 85,
},
},
};
106 changes: 106 additions & 0 deletions src/client/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -783,6 +783,25 @@ export interface CreateWalletRequestWallet {
*/
'use_server_signer'?: boolean;
}
/**
*
* @export
* @interface CreateWalletWebhookRequest
*/
export interface CreateWalletWebhookRequest {
/**
* The URL to which the notifications will be sent
* @type {string}
* @memberof CreateWalletWebhookRequest
*/
'notification_uri': string;
/**
* The custom header to be used for x-webhook-signature header on callbacks, so developers can verify the requests are coming from Coinbase.
* @type {string}
* @memberof CreateWalletWebhookRequest
*/
'signature_header'?: string;
}
/**
*
* @export
Expand Down Expand Up @@ -9288,6 +9307,44 @@ export class WalletsApi extends BaseAPI implements WalletsApiInterface {
*/
export const WebhooksApiAxiosParamCreator = function (configuration?: Configuration) {
return {
/**
* Create a new webhook scoped to a wallet
* @summary Create a new webhook scoped to a wallet
* @param {string} walletId The ID of the wallet to create the webhook for.
* @param {CreateWalletWebhookRequest} [createWalletWebhookRequest]
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
createWalletWebhook: async (walletId: string, createWalletWebhookRequest?: CreateWalletWebhookRequest, options: RawAxiosRequestConfig = {}): Promise<RequestArgs> => {
// verify required parameter 'walletId' is not null or undefined
assertParamExists('createWalletWebhook', 'walletId', walletId)
const localVarPath = `/v1/wallets/{wallet_id}/webhooks`
.replace(`{${"wallet_id"}}`, encodeURIComponent(String(walletId)));
// use dummy base URL string because the URL constructor only accepts absolute URLs.
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
let baseOptions;
if (configuration) {
baseOptions = configuration.baseOptions;
}

const localVarRequestOptions = { method: 'POST', ...baseOptions, ...options};
const localVarHeaderParameter = {} as any;
const localVarQueryParameter = {} as any;



localVarHeaderParameter['Content-Type'] = 'application/json';

setSearchParams(localVarUrlObj, localVarQueryParameter);
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
localVarRequestOptions.data = serializeDataIfNeeded(createWalletWebhookRequest, localVarRequestOptions, configuration)

return {
url: toPathString(localVarUrlObj),
options: localVarRequestOptions,
};
},
/**
* Create a new webhook
* @summary Create a new webhook
Expand Down Expand Up @@ -9444,6 +9501,20 @@ export const WebhooksApiAxiosParamCreator = function (configuration?: Configurat
export const WebhooksApiFp = function(configuration?: Configuration) {
const localVarAxiosParamCreator = WebhooksApiAxiosParamCreator(configuration)
return {
/**
* Create a new webhook scoped to a wallet
* @summary Create a new webhook scoped to a wallet
* @param {string} walletId The ID of the wallet to create the webhook for.
* @param {CreateWalletWebhookRequest} [createWalletWebhookRequest]
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async createWalletWebhook(walletId: string, createWalletWebhookRequest?: CreateWalletWebhookRequest, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<Webhook>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.createWalletWebhook(walletId, createWalletWebhookRequest, options);
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
const localVarOperationServerBasePath = operationServerMap['WebhooksApi.createWalletWebhook']?.[localVarOperationServerIndex]?.url;
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
},
/**
* Create a new webhook
* @summary Create a new webhook
Expand Down Expand Up @@ -9508,6 +9579,17 @@ export const WebhooksApiFp = function(configuration?: Configuration) {
export const WebhooksApiFactory = function (configuration?: Configuration, basePath?: string, axios?: AxiosInstance) {
const localVarFp = WebhooksApiFp(configuration)
return {
/**
* Create a new webhook scoped to a wallet
* @summary Create a new webhook scoped to a wallet
* @param {string} walletId The ID of the wallet to create the webhook for.
* @param {CreateWalletWebhookRequest} [createWalletWebhookRequest]
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
createWalletWebhook(walletId: string, createWalletWebhookRequest?: CreateWalletWebhookRequest, options?: RawAxiosRequestConfig): AxiosPromise<Webhook> {
return localVarFp.createWalletWebhook(walletId, createWalletWebhookRequest, options).then((request) => request(axios, basePath));
},
/**
* Create a new webhook
* @summary Create a new webhook
Expand Down Expand Up @@ -9559,6 +9641,17 @@ export const WebhooksApiFactory = function (configuration?: Configuration, baseP
* @interface WebhooksApi
*/
export interface WebhooksApiInterface {
/**
* Create a new webhook scoped to a wallet
* @summary Create a new webhook scoped to a wallet
* @param {string} walletId The ID of the wallet to create the webhook for.
* @param {CreateWalletWebhookRequest} [createWalletWebhookRequest]
* @param {*} [options] Override http request option.
* @throws {RequiredError}
* @memberof WebhooksApiInterface
*/
createWalletWebhook(walletId: string, createWalletWebhookRequest?: CreateWalletWebhookRequest, options?: RawAxiosRequestConfig): AxiosPromise<Webhook>;

/**
* Create a new webhook
* @summary Create a new webhook
Expand Down Expand Up @@ -9610,6 +9703,19 @@ export interface WebhooksApiInterface {
* @extends {BaseAPI}
*/
export class WebhooksApi extends BaseAPI implements WebhooksApiInterface {
/**
* Create a new webhook scoped to a wallet
* @summary Create a new webhook scoped to a wallet
* @param {string} walletId The ID of the wallet to create the webhook for.
* @param {CreateWalletWebhookRequest} [createWalletWebhookRequest]
* @param {*} [options] Override http request option.
* @throws {RequiredError}
* @memberof WebhooksApi
*/
public createWalletWebhook(walletId: string, createWalletWebhookRequest?: CreateWalletWebhookRequest, options?: RawAxiosRequestConfig) {
return WebhooksApiFp(this.configuration).createWalletWebhook(walletId, createWalletWebhookRequest, options).then((request) => request(this.axios, this.basePath));
}

/**
* Create a new webhook
* @summary Create a new webhook
Expand Down
18 changes: 18 additions & 0 deletions src/coinbase/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ import {
CreateSmartContractRequest,
SmartContract as SmartContractModel,
DeploySmartContractRequest,
WebhookEventTypeFilter,
CreateWalletWebhookRequest,
} from "./../client/api";
import { Address } from "./address";
import { Wallet } from "./wallet";
Expand Down Expand Up @@ -1038,6 +1040,21 @@ export type ListHistoricalBalancesResult = {
};

export interface WebhookApiClient {
/**
* Create a new webhook for a wallet
*
* @summary Create a new webhook for a wallet
* @param {string} [walletId]
* @param {CreateWalletWebhookRequest} [createWalletWebhookRequest]
* @param {*} [options] - Override http request option.
* @throws {RequiredError}
*/
createWalletWebhook(
walletId?: string,
createWalletWebhookRequest?: CreateWalletWebhookRequest,
options?: RawAxiosRequestConfig,
): AxiosPromise<WebhookModel>;

/**
* Create a new webhook
*
Expand Down Expand Up @@ -1187,6 +1204,7 @@ export type CreateWebhookOptions = {
networkId: string;
notificationUri: string;
eventType: WebhookEventType;
eventTypeFilter?: WebhookEventTypeFilter;
eventFilters?: Array<WebhookEventFilter>;
signatureHeader?: string;
};
Expand Down
16 changes: 16 additions & 0 deletions src/coinbase/wallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import { StakingBalance } from "./staking_balance";
import { PayloadSignature } from "./payload_signature";
import { ContractInvocation } from "../coinbase/contract_invocation";
import { SmartContract } from "./smart_contract";
import { Webhook } from "./webhook";

/**
* A representation of a Wallet. Wallets come with a single default Address, but can expand to have a set of Addresses,
Expand Down Expand Up @@ -750,6 +751,21 @@ export class Wallet {
return (await this.getDefaultAddress()).createPayloadSignature(unsignedPayload);
}

/**
* Creates a Webhook for a wallet, monitors all wallet addresses for onchain events.
*
* @param notificationUri - The URI to which the webhook notifications will be sent.
*
* @returns The newly created webhook instance.
*/
public async createWebhook(notificationUri: string): Promise<Webhook> {
const result = await Coinbase.apiClients.webhook!.createWalletWebhook(this.getId(), {
notification_uri: notificationUri,
});

return Webhook.init(result.data);
}

/**
* Invokes a contract with the given data.
*
Expand Down
24 changes: 19 additions & 5 deletions src/coinbase/webhook.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import { Webhook as WebhookModel, WebhookEventType, WebhookEventFilter } from "../client/api";
import {
Webhook as WebhookModel,
WebhookEventType,
WebhookEventFilter,
WebhookEventTypeFilter,
} from "../client/api";
import { Coinbase } from "./coinbase";
import { CreateWebhookOptions } from "./types";

Expand Down Expand Up @@ -40,24 +45,23 @@ export class Webhook {
* @param options.networkId - The network ID for which the webhook is created.
* @param options.notificationUri - The URI where notifications should be sent.
* @param options.eventType - The type of event for the webhook.
* @param options.eventTypeFilter - Filter for wallet activity event type.
* @param options.eventFilters - Filters applied to the events that determine which specific events trigger the webhook.
* @param options.signatureHeader - The custom header to be used for x-webhook-signature header on callbacks,
* so developers can verify the requests are coming from Coinbase.
* @returns A promise that resolves to a new instance of Webhook.
*/
public static async create({
networkId,
notificationUri,
eventType,
eventTypeFilter,
eventFilters = [],
signatureHeader = "",
}: CreateWebhookOptions): Promise<Webhook> {
const result = await Coinbase.apiClients.webhook!.createWebhook({
network_id: networkId,
notification_uri: notificationUri,
event_type: eventType,
event_type_filter: eventTypeFilter,
event_filters: eventFilters,
signature_header: signatureHeader,
});

return new Webhook(result.data);
Expand Down Expand Up @@ -131,6 +135,15 @@ export class Webhook {
return this.model?.event_type;
}

/**
* Returns the event type filter of the webhook.
*
* @returns The filter which will be used to filter for events of a certain event type
*/
public getEventTypeFilter(): WebhookEventTypeFilter | undefined {
return this.model?.event_type_filter;
}

/**
* Returns the event filters applied to the webhook.
*
Expand Down Expand Up @@ -186,6 +199,7 @@ export class Webhook {
return (
`Webhook { id: '${this.getId()}', networkId: '${this.getNetworkId()}', ` +
`eventType: '${this.getEventType()}', eventFilter: ${JSON.stringify(this.getEventFilters())}, ` +
`eventTypeFilter: ${JSON.stringify(this.getEventTypeFilter())}, ` +
`notificationUri: '${this.getNotificationURI()}', signatureHeader: '${this.getSignatureHeader()}' }`
);
}
Expand Down
Loading

0 comments on commit a9a9864

Please sign in to comment.