Skip to content

Commit 4f822e4

Browse files
committed
Auto-set no_dispense (#173)
When sending BTC to an address that belongs to the active wallet, automatically set no_dispense=true to prevent accidentally triggering dispensers at the destination address. - Add no_dispense option to SendOptions interface - Pass no_dispense parameter to compose API - Detect own-address BTC sends in composer context
1 parent f23d936 commit 4f822e4

3 files changed

Lines changed: 19 additions & 4 deletions

File tree

src/pages/compose/send/form.tsx

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { AmountWithMaxInput } from "@/components/ui/inputs/amount-with-max-input
66
import { DestinationsInput } from "@/components/ui/inputs/destinations-input";
77
import { MemoInput } from "@/components/ui/inputs/memo-input";
88
import { useComposer } from "@/contexts/composer-context";
9+
import { useWallet } from "@/contexts/wallet-context";
910
import { useAssetDetails } from "@/hooks/useAssetDetails";
1011
import { validateQuantity } from "@/utils/validation/amount";
1112
import type { SendOptions } from "@/utils/blockchain/counterparty/compose";
@@ -26,6 +27,7 @@ export function SendForm({
2627
}: SendFormProps): ReactElement {
2728
// Get everything from composer context
2829
const { activeAddress, settings, showHelpText, feeRate } = useComposer<SendOptions>();
30+
const { activeWallet } = useWallet();
2931
const enableMPMA = settings?.enableMPMA ?? false;
3032

3133
// Data fetching hooks
@@ -87,22 +89,31 @@ export function SendForm({
8789
if (amount) {
8890
formData.set("quantity", amount);
8991
}
90-
92+
93+
const asset = initialAsset || initialFormData?.asset || "BTC";
94+
9195
// Add all destinations to form data
9296
if (destinations.length > 1) {
9397
// For MPMA, pass destinations as comma-separated list
9498
formData.set("destinations", destinations.map(d => d.address).join(","));
9599
formData.delete("destination"); // Remove single destination field
96100
} else {
97101
// For single send, use the first destination
98-
formData.set("destination", destinations[0].address);
102+
const destination = destinations[0].address;
103+
formData.set("destination", destination);
104+
105+
// Prevent triggering own dispensers when sending BTC to self
106+
const isOwnAddress = activeWallet?.addresses.some(a => a.address === destination);
107+
if (asset === "BTC" && isOwnAddress) {
108+
formData.set("no_dispense", "true");
109+
}
99110
}
100-
111+
101112
// Add memo to form data
102113
if (memo) {
103114
formData.set("memo", memo);
104115
}
105-
116+
106117
formAction(formData);
107118
};
108119

src/utils/blockchain/counterparty/compose.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,7 @@ export interface SendOptions extends BaseComposeOptions {
200200
quantity: number;
201201
memo?: string;
202202
memo_is_hex?: boolean;
203+
no_dispense?: boolean;
203204
}
204205

205206
export interface SweepOptions extends BaseComposeOptions {
@@ -837,6 +838,7 @@ export async function composeSend(options: SendOptions): Promise<ApiResponse> {
837838
quantity,
838839
memo,
839840
memo_is_hex,
841+
no_dispense,
840842
sat_per_vbyte,
841843
max_fee,
842844
encoding,
@@ -847,6 +849,7 @@ export async function composeSend(options: SendOptions): Promise<ApiResponse> {
847849
quantity: quantity.toString(),
848850
...(memo !== undefined ? { memo } : {}),
849851
...(memo_is_hex !== undefined ? { memo_is_hex: memo_is_hex.toString() } : {}),
852+
...(no_dispense !== undefined ? { no_dispense: no_dispense.toString() } : {}),
850853
...(max_fee !== undefined && { max_fee: max_fee.toString() }),
851854
};
852855
return composeTransaction('send', paramsObj, sourceAddress, sat_per_vbyte, encoding);

src/utils/blockchain/counterparty/normalize.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ const NORMALIZATION_CONFIG: Record<string, {
4646
send: {
4747
quantityFields: ['quantity'],
4848
assetFields: { quantity: 'asset' },
49+
booleanFields: ['no_dispense'],
4950
memoConfig: { type: 'boolean', field: 'memo_is_hex' }
5051
},
5152
order: {

0 commit comments

Comments
 (0)