Skip to content

Commit

Permalink
Gix 1331 tx too old error handler (#296)
Browse files Browse the repository at this point in the history
# Motivation

Add `notifyPaymentFailure` api.
Needs for https://dfinity.atlassian.net/browse/GIX-1331.

# Changes

- canister / `notifyPaymentFailure` 
- wrapper / `notifyPaymentFailure`

# Tests

- canister / `notifyPaymentFailure` 
- wrapper / `notifyPaymentFailure`

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
  • Loading branch information
mstrasinskis and github-actions[bot] authored Feb 22, 2023
1 parent 13c2dc7 commit 76d180e
Show file tree
Hide file tree
Showing 9 changed files with 76 additions and 13 deletions.
22 changes: 22 additions & 0 deletions packages/sns/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,7 @@ Source code: https://github.com/dfinity/ic/blob/master/rs/sns/root/src/lib.rs

- [create](#gear-create)
- [state](#gear-state)
- [notifyPaymentFailure](#gear-notifypaymentfailure)
- [notifyParticipation](#gear-notifyparticipation)
- [getUserCommitment](#gear-getusercommitment)
- [getDerivedState](#gear-getderivedstate)
Expand All @@ -378,6 +379,14 @@ Get the state of the swap
| ------- | ---------------------------------------------------- |
| `state` | `(params: QueryParams) => Promise<GetStateResponse>` |

##### :gear: notifyPaymentFailure

Notify of the payment failure to remove the ticket

| Method | Type |
| ---------------------- | ----------------------- |
| `notifyPaymentFailure` | `() => Promise<Ticket>` |

##### :gear: notifyParticipation

Notify of the user participating in the swap
Expand Down Expand Up @@ -479,6 +488,7 @@ Parameters:
- [setTopicFollowees](#gear-settopicfollowees)
- [registerVote](#gear-registervote)
- [swapState](#gear-swapstate)
- [notifyPaymentFailure](#gear-notifypaymentfailure)
- [notifyParticipation](#gear-notifyparticipation)
- [getUserCommitment](#gear-getusercommitment)
- [getOpenTicket](#gear-getopenticket)
Expand Down Expand Up @@ -688,6 +698,18 @@ This is a convenient method that transfers the stake to the neuron subaccount an
| ----------- | ----------------------------------------------------------------------- |
| `swapState` | `(params: Omit<QueryParams, "certified">) => Promise<GetStateResponse>` |

##### :gear: notifyPaymentFailure

Returns the ticket if a ticket was found for the caller and the ticket
was removed successfully. Returns None if no ticket was found for the caller.
Only the owner of a ticket can remove it.

Always certified

| Method | Type |
| ---------------------- | ----------------------- |
| `notifyPaymentFailure` | `() => Promise<Ticket>` |

##### :gear: notifyParticipation

| Method | Type |
Expand Down
6 changes: 6 additions & 0 deletions packages/sns/candid/sns_swap.certified.idl.js
Original file line number Diff line number Diff line change
Expand Up @@ -185,11 +185,16 @@ export const idlFactory = ({ IDL }) => {
});
const Swap = IDL.Record({
'neuron_recipes' : IDL.Vec(SnsNeuronRecipe),
'next_ticket_id' : IDL.Opt(IDL.Nat64),
'decentralization_sale_open_timestamp_seconds' : IDL.Opt(IDL.Nat64),
'finalize_swap_in_progress' : IDL.Opt(IDL.Bool),
'cf_participants' : IDL.Vec(CfParticipant),
'init' : IDL.Opt(Init),
'purge_old_tickets_last_completion_timestamp_nanoseconds' : IDL.Opt(
IDL.Nat64
),
'lifecycle' : IDL.Int32,
'purge_old_tickets_next_principal' : IDL.Opt(IDL.Vec(IDL.Nat8)),
'buyers' : IDL.Vec(IDL.Tuple(IDL.Text, BuyerState)),
'params' : IDL.Opt(Params),
'open_sns_token_swap_proposal_id' : IDL.Opt(IDL.Nat64),
Expand Down Expand Up @@ -308,6 +313,7 @@ export const idlFactory = ({ IDL }) => {
[NewSaleTicketResponse],
[],
),
'notify_payment_failure' : IDL.Func([IDL.Record({})], [Ok_1], []),
'open' : IDL.Func([OpenRequest], [IDL.Record({})], []),
'refresh_buyer_tokens' : IDL.Func(
[RefreshBuyerTokensRequest],
Expand Down
4 changes: 4 additions & 0 deletions packages/sns/candid/sns_swap.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -243,11 +243,14 @@ export interface SnsNeuronRecipe {
}
export interface Swap {
neuron_recipes: Array<SnsNeuronRecipe>;
next_ticket_id: [] | [bigint];
decentralization_sale_open_timestamp_seconds: [] | [bigint];
finalize_swap_in_progress: [] | [boolean];
cf_participants: Array<CfParticipant>;
init: [] | [Init];
purge_old_tickets_last_completion_timestamp_nanoseconds: [] | [bigint];
lifecycle: number;
purge_old_tickets_next_principal: [] | [Uint8Array];
buyers: Array<[string, BuyerState]>;
params: [] | [Params];
open_sns_token_swap_proposal_id: [] | [bigint];
Expand Down Expand Up @@ -298,6 +301,7 @@ export interface _SERVICE {
ListSnsNeuronRecipesResponse
>;
new_sale_ticket: ActorMethod<[NewSaleTicketRequest], NewSaleTicketResponse>;
notify_payment_failure: ActorMethod<[{}], Ok_1>;
open: ActorMethod<[OpenRequest], {}>;
refresh_buyer_tokens: ActorMethod<
[RefreshBuyerTokensRequest],
Expand Down
6 changes: 5 additions & 1 deletion packages/sns/candid/sns_swap.did
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Generated from IC repo commit 5376a14c92f20b4bd285d7622ac5f2a8d21c0d02 'rs/sns/swap/canister/swap.did' by import-candid
// Generated from IC repo commit a548beb5bc0e1be2de4162c0dd4d647ecfd4f413 'rs/sns/swap/canister/swap.did' by import-candid
type BuyerState = record { icp : opt TransferableAmount };
type CanisterCallError = record { code : opt int32; description : text };
type CanisterStatusResultV2 = record {
Expand Down Expand Up @@ -173,11 +173,14 @@ type SnsNeuronRecipe = record {
};
type Swap = record {
neuron_recipes : vec SnsNeuronRecipe;
next_ticket_id : opt nat64;
decentralization_sale_open_timestamp_seconds : opt nat64;
finalize_swap_in_progress : opt bool;
cf_participants : vec CfParticipant;
init : opt Init;
purge_old_tickets_last_completion_timestamp_nanoseconds : opt nat64;
lifecycle : int32;
purge_old_tickets_next_principal : opt vec nat8;
buyers : vec record { text; BuyerState };
params : opt Params;
open_sns_token_swap_proposal_id : opt nat64;
Expand Down Expand Up @@ -222,6 +225,7 @@ service : (Init) -> {
ListSnsNeuronRecipesResponse,
) query;
new_sale_ticket : (NewSaleTicketRequest) -> (NewSaleTicketResponse);
notify_payment_failure : (record {}) -> (Ok_1);
open : (OpenRequest) -> (record {});
refresh_buyer_tokens : (RefreshBuyerTokensRequest) -> (
RefreshBuyerTokensResponse,
Expand Down
6 changes: 6 additions & 0 deletions packages/sns/candid/sns_swap.idl.js
Original file line number Diff line number Diff line change
Expand Up @@ -185,11 +185,16 @@ export const idlFactory = ({ IDL }) => {
});
const Swap = IDL.Record({
'neuron_recipes' : IDL.Vec(SnsNeuronRecipe),
'next_ticket_id' : IDL.Opt(IDL.Nat64),
'decentralization_sale_open_timestamp_seconds' : IDL.Opt(IDL.Nat64),
'finalize_swap_in_progress' : IDL.Opt(IDL.Bool),
'cf_participants' : IDL.Vec(CfParticipant),
'init' : IDL.Opt(Init),
'purge_old_tickets_last_completion_timestamp_nanoseconds' : IDL.Opt(
IDL.Nat64
),
'lifecycle' : IDL.Int32,
'purge_old_tickets_next_principal' : IDL.Opt(IDL.Vec(IDL.Nat8)),
'buyers' : IDL.Vec(IDL.Tuple(IDL.Text, BuyerState)),
'params' : IDL.Opt(Params),
'open_sns_token_swap_proposal_id' : IDL.Opt(IDL.Nat64),
Expand Down Expand Up @@ -316,6 +321,7 @@ export const idlFactory = ({ IDL }) => {
[NewSaleTicketResponse],
[],
),
'notify_payment_failure' : IDL.Func([IDL.Record({})], [Ok_1], []),
'open' : IDL.Func([OpenRequest], [IDL.Record({})], []),
'refresh_buyer_tokens' : IDL.Func(
[RefreshBuyerTokensRequest],
Expand Down
5 changes: 5 additions & 0 deletions packages/sns/src/sns.wrapper.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,11 @@ describe("SnsWrapper", () => {
});
});

it("should call notifyPaymentFailure", async () => {
await snsWrapper.notifyPaymentFailure();
expect(mockSwapCanister.notifyPaymentFailure).toHaveBeenCalledWith();
});

it("should call notifyParticipation", async () => {
await snsWrapper.notifyParticipation({ buyer: "aaaaa-aa" });
expect(mockSwapCanister.notifyParticipation).toHaveBeenCalledWith({
Expand Down
12 changes: 12 additions & 0 deletions packages/sns/src/sns.wrapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,18 @@ export class SnsWrapper {
params: Omit<QueryParams, "certified">
): Promise<GetStateResponse> => this.swap.state(this.mergeParams(params));

/**
* Returns the ticket if a ticket was found for the caller and the ticket
* was removed successfully. Returns None if no ticket was found for the caller.
* Only the owner of a ticket can remove it.
*
* Always certified
*
* @param params
*/
notifyPaymentFailure = (): Promise<Ticket | undefined> =>
this.swap.notifyPaymentFailure();

// Always certified
notifyParticipation = (
params: RefreshBuyerTokensRequest
Expand Down
18 changes: 6 additions & 12 deletions packages/sns/src/swap.canister.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -235,27 +235,21 @@ describe("Swap canister", () => {
expect(res).toEqual(mockResponse);
});

it("should call to notify the buyer tokens", async () => {
it("should call to notify payment failure", async () => {
const service = mock<ActorSubclass<SnsSwapService>>();
service.refresh_buyer_tokens.mockResolvedValue({
icp_accepted_participation_e8s: BigInt(123),
icp_ledger_account_balance_e8s: BigInt(321),
service.notify_payment_failure.mockResolvedValue({
ticket: [saleTicketMock],
});

const canister = SnsSwapCanister.create({
canisterId: swapCanisterIdMock,
certifiedServiceOverride: service,
});
const result = await canister.notifyParticipation({ buyer: "aaaaa-aa" });
const result = await canister.notifyPaymentFailure();

expect(service.refresh_buyer_tokens).toHaveBeenCalledWith({
buyer: "aaaaa-aa",
});
expect(service.notify_payment_failure).toHaveBeenCalledWith({});

expect(result).toEqual({
icp_accepted_participation_e8s: 123n,
icp_ledger_account_balance_e8s: 321n,
});
expect(result).toEqual(saleTicketMock);
});

it("should return the user commitment", async () => {
Expand Down
10 changes: 10 additions & 0 deletions packages/sns/src/swap.canister.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,16 @@ export class SnsSwapCanister extends Canister<SnsSwapService> {
state = (params: QueryParams): Promise<GetStateResponse> =>
this.caller(params).get_state({});

/**
* Notify of the payment failure to remove the ticket
*/
notifyPaymentFailure = async (): Promise<Ticket | undefined> => {
const { ticket } = await this.caller({
certified: true,
}).notify_payment_failure({});
return fromNullable(ticket);
};

/**
* Notify of the user participating in the swap
*/
Expand Down

0 comments on commit 76d180e

Please sign in to comment.