Skip to content

Commit

Permalink
feat: improved print events for bridge functions
Browse files Browse the repository at this point in the history
  • Loading branch information
dumbledope committed Jun 29, 2022
1 parent c3741ed commit 3027586
Show file tree
Hide file tree
Showing 5 changed files with 189 additions and 4 deletions.
5 changes: 5 additions & 0 deletions .changeset/short-plums-sing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'bridge-ui': minor
---

Added better `print` events to major contract calls, which allows for better off-chain monitoring.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,4 @@ yarn-error.log*

settings/Testnet.toml
.clarinet
history.txt
93 changes: 93 additions & 0 deletions common/events.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import { contracts } from './clarigen/single';
import type { TypedAbiFunction } from '@clarigen/core';

type ResponseType<T> = T extends TypedAbiFunction<unknown[], infer R> ? R : never;

type BridgeFunctions = typeof contracts['bridge']['functions'];

type InboundSwapResponse = NonNullable<ResponseType<BridgeFunctions['getInboundSwap']>>;

type InboundSwapMeta = NonNullable<ResponseType<BridgeFunctions['getInboundMeta']>>;

type OutboundSwapResponse = NonNullable<ResponseType<BridgeFunctions['getOutboundSwap']>>;

export type InboundSwapFull = InboundSwapResponse & InboundSwapMeta;

export type EscrowPrint = InboundSwapFull & {
topic: 'escrow';
txid: Uint8Array;
};

export type FinalizeInboundPrint = InboundSwapResponse & {
topic: 'finalize-inbound';
preimage: Uint8Array;
txid: Uint8Array;
};

export type RevokeInboundPrint = InboundSwapResponse & {
topic: 'revoke-inbound';
txid: Uint8Array;
};

export type InitiateOutboundPrint = OutboundSwapResponse & {
topic: 'initiate-outbound';
'swap-id': BigInt;
};

export type FinalizeOutboundPrint = OutboundSwapResponse & {
topic: 'finalize-outbound';
'swap-id': BigInt;
txid: Uint8Array;
};

export type RevokeOutboundPrint = OutboundSwapResponse & {
topic: 'revoke-outbound';
'swap-id': BigInt;
};

export type Prints =
| EscrowPrint
| FinalizeInboundPrint
| RevokeInboundPrint
| InitiateOutboundPrint
| FinalizeOutboundPrint
| RevokeOutboundPrint;

export const isEscrowPrint = (val: Prints): val is EscrowPrint => val.topic === 'escrow';
export const isFinalizeInboundPrint = (val: Prints): val is FinalizeInboundPrint =>
val.topic === 'finalize-inbound';
export const isRevokeInboundPrint = (val: Prints): val is RevokeInboundPrint =>
val.topic === 'revoke-inbound';
export const isInitiateOutboundPrint = (val: Prints): val is InitiateOutboundPrint =>
val.topic === 'initiate-outbound';
export const isFinalizeOutboundPrint = (val: Prints): val is FinalizeOutboundPrint =>
val.topic === 'finalize-outbound';
export const isRevokeOutboundPrint = (val: Prints): val is RevokeOutboundPrint =>
val.topic === 'revoke-outbound';

export function getEventWithPrint<T extends Prints>(prints: Prints[], topic: T['topic']): T {
const [found] = prints.filter(p => p.topic === topic);
if (typeof found === 'undefined') {
throw new Error(`No print with topic '${topic}'`);
}
return found as T;
}

export function getEscrowPrint(prints: Prints[]) {
return getEventWithPrint<EscrowPrint>(prints, 'escrow');
}
export function getFinalizeInboundPrint(prints: Prints[]) {
return getEventWithPrint<FinalizeInboundPrint>(prints, 'finalize-inbound');
}
export function getRevokeInboundPrint(prints: Prints[]) {
return getEventWithPrint<RevokeInboundPrint>(prints, 'revoke-inbound');
}
export function getInitiateOutboundPrint(prints: Prints[]) {
return getEventWithPrint<InitiateOutboundPrint>(prints, 'initiate-outbound');
}
export function getFinalizeOutboundPrint(prints: Prints[]) {
return getEventWithPrint<FinalizeOutboundPrint>(prints, 'finalize-outbound');
}
export function getRevokeOutboundPrint(prints: Prints[]) {
return getEventWithPrint<RevokeOutboundPrint>(prints, 'revoke-outbound');
}
28 changes: 26 additions & 2 deletions contracts/bridge.clar
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,6 @@
redeem-script: htlc-redeem,
sats: sats,
})
(event (merge escrow meta))
)
;; assert tx-sender is swapper
(asserts! (is-eq tx-sender (unwrap! (map-get? swapper-by-id swapper-id) ERR_SWAPPER_NOT_FOUND)) ERR_UNAUTHORIZED)
Expand All @@ -351,7 +350,10 @@
(asserts! (>= xbtc min-to-receive) ERR_INCONSISTENT_FEES)
(map-set supplier-funds supplier-id new-funds)
(map-set supplier-escrow supplier-id new-escrow)
(print (merge event { topic: "escrow" }))
(print (merge (merge escrow meta) {
topic: "escrow",
txid: txid,
}))
(ok meta)
)
)
Expand Down Expand Up @@ -382,6 +384,11 @@
(asserts! (>= (get expiration swap) block-height) ERR_ESCROW_EXPIRED)
(map-set supplier-escrow supplier-id (- escrowed xbtc))
(update-user-inbound-volume swapper xbtc)
(print (merge swap {
preimage: preimage,
topic: "finalize-inbound",
txid: txid,
}))
(ok swap)
)
)
Expand Down Expand Up @@ -418,6 +425,10 @@
(map-insert inbound-preimages txid REVOKED_INBOUND_PREIMAGE)
(map-set supplier-escrow supplier-id new-escrow)
(map-set supplier-funds supplier-id new-funds)
(print (merge swap {
topic: "revoke-inbound",
txid: txid,
}))
(ok swap)
)
)
Expand Down Expand Up @@ -455,6 +466,10 @@
(try! (transfer xbtc tx-sender (as-contract tx-sender)))
(asserts! (map-insert outbound-swaps swap-id swap) ERR_PANIC)
(var-set next-outbound-id (+ swap-id u1))
(print (merge swap {
swap-id: swap-id,
topic: "initiate-outbound",
}))
(ok swap-id)
)
)
Expand Down Expand Up @@ -502,6 +517,11 @@
(asserts! (map-insert completed-outbound-swap-txids txid swap-id) ERR_TXID_USED)
(asserts! (>= output-sats (get sats swap)) ERR_INSUFFICIENT_AMOUNT)
(update-user-outbound-volume (get swapper swap) xbtc)
(print (merge swap {
topic: "finalize-outbound",
txid: txid,
swap-id: swap-id,
}))
(ok true)
)
)
Expand All @@ -522,6 +542,10 @@
)
(try! (as-contract (transfer xbtc tx-sender swapper)))
(asserts! (map-insert completed-outbound-swaps swap-id REVOKED_OUTBOUND_TXID) ERR_PANIC)
(print (merge swap {
topic: "revoke-outbound",
swap-id: swap-id,
}))
(ok swap)
)
)
Expand Down
66 changes: 64 additions & 2 deletions test/bridge.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,14 @@ import { NativeClarityBinProvider } from '@clarigen/native-bin';
import { ContractReturn, CoreNodeEventType, filterEvents } from '@clarigen/core';
import { makeRandomPrivKey } from 'micro-stacks/transactions';
import { contracts as contractDef } from '../common/clarigen/single';
import {
getEscrowPrint,
getFinalizeInboundPrint,
getFinalizeOutboundPrint,
getInitiateOutboundPrint,
getRevokeInboundPrint,
getRevokeOutboundPrint,
} from '../common/events';

let contract: BridgeContract;
let xbtcContract: XbtcContract;
Expand Down Expand Up @@ -306,7 +314,15 @@ describe('successful inbound swap', () => {
),
swapper
);
// logTxCosts(receipt.costs, 'escrowSwap');
const printEvent = getEscrowPrint(receipt.prints);
const { 'swapper-principal': swapperPrincipal, ...swap } = await t.rovOk(
contract.getFullInbound(txid)
);
expect(printEvent).toEqual({
...swap,
topic: 'escrow',
txid,
});
});
test('validates that escrow stored', async () => {
const swap = await t.rov(contract.getInboundSwap(txid));
Expand Down Expand Up @@ -367,7 +383,18 @@ describe('successful inbound swap', () => {
let finalizeReceipt: PublicResultOk<any>;

test('can finalize an escrow', async () => {
finalizeReceipt = await t.txOk(contract.finalizeSwap(txid, Buffer.from(preImage)), swapper);
finalizeReceipt = await t.txOk(contract.finalizeSwap(txid, preImage), swapper);
});

test('finalize has proper print', async () => {
const print = getFinalizeInboundPrint(finalizeReceipt.prints);
const swap = await getInboundSwap(txid);
expect(print).toEqual({
...swap,
txid,
preimage: preImage,
topic: 'finalize-inbound',
});
});

test('validates proper amount of xbtc moved', () => {
Expand Down Expand Up @@ -802,6 +829,13 @@ describe('validating inbound swaps', () => {
const escrow = (await t.rov(contract.getEscrow(supplier)))!;
expect(funds).toEqual(fundsBefore + xbtc);
expect(escrow).toEqual(escrowBefore - xbtc);

const print = getRevokeInboundPrint(receipt.prints);
expect(print).toEqual({
...swap,
topic: 'revoke-inbound',
txid,
});
});

test('cannot revoke already revoked inbound swap', async () => {
Expand Down Expand Up @@ -843,6 +877,16 @@ describe('successful outbound swap', () => {
expect(receipt.value).toEqual(swapId);
});

test('has correct print', async () => {
const swap = (await t.rov(contract.getOutboundSwap(swapId)))!;
const print = getInitiateOutboundPrint(receipt.prints);
expect(print).toEqual({
...swap,
'swap-id': swapId,
topic: 'initiate-outbound',
});
});

test('tx sent the right amount of xbtc', async () => {
const tokensMoved = receipt.assets.tokens[swapper][xbtcTokenId];
expect(tokensMoved).toEqual(xbtcAmount.toString());
Expand Down Expand Up @@ -881,6 +925,15 @@ describe('successful outbound swap', () => {
),
supplier
);

const print = getFinalizeOutboundPrint(receipt.prints);
const swap = (await t.rov(contract.getOutboundSwap(swapId)))!;
expect(print).toEqual({
...swap,
topic: 'finalize-outbound',
txid,
'swap-id': swapId,
});
});

test('Swap saved as completed', async () => {
Expand Down Expand Up @@ -978,6 +1031,15 @@ describe('revoking outbound swap', () => {
expect(ftTransfer.ft_transfer_event.asset_identifier).toEqual(xbtcTokenId);

expect(receipt.assets.tokens[bridgeId][xbtcTokenId]).toEqual(xbtcAmount.toString());

const swap = (await t.rov(contract.getOutboundSwap(swapId)))!;

const print = getRevokeOutboundPrint(receipt.prints);
expect(print).toEqual({
...swap,
topic: 'revoke-outbound',
'swap-id': swapId,
});
});

test('cannot finalize an outbound swap after revoked', async () => {
Expand Down

0 comments on commit 3027586

Please sign in to comment.