Table of Contents

Class ClaimPacket

Namespace
NArk.ArkadeIntents.Lightning
Assembly
NArk.ArkadeIntents.dll

Seals a receive swap's preimage to covclaimd, so the claim can be pushed while the client is offline without the solver ever learning the secret.

public static class ClaimPacket
Inheritance
ClaimPacket
Inherited Members

Remarks

The asymmetry is the point. On a receive swap the solver funds the Arkade side before the Lightning payment it is owed has settled, and it only gets paid when the preimage surfaces in a claim witness. If the solver could open this packet it could settle without ever paying out, so the encryption is to covclaimd's key — not the solver's — and the solver carries it as opaque bytes it cannot read.

The scheme is ECIES over secp256k1: an ephemeral key, ECDH, HKDF-SHA256, then AES-256-GCM with the ephemeral public key as additional data. One detail is easy to get wrong and impossible to catch locally — the ECDH shared secret is the 32-byte X coordinate alone, not the compressed point some libraries hand back.

Methods

NewAsync(string, IAesGcmCipher?, CancellationToken)

Generate a fresh 32-byte preimage and seal it — how a receive swap starts.

public static Task<SealedClaimPacket> NewAsync(string covclaimdPubKeyHex, IAesGcmCipher? cipher = null, CancellationToken cancellationToken = default)

Parameters

covclaimdPubKeyHex string

covclaimd's compressed secp256k1 key, hex.

cipher IAesGcmCipher
cancellationToken CancellationToken

Returns

Task<SealedClaimPacket>

The packet, the preimage and its payment hash.

PaymentHashOf(byte[])

The payment hash a preimage settles against: sha256(preimage), hex.

public static string PaymentHashOf(byte[] preimage)

Parameters

preimage byte[]

The 32-byte secret.

Returns

string

64 lowercase hex characters.

Remarks

Needed on its own because sealing is optional: a client with no covclaimd sends no packet, and still has to name the hash its quote is requested against.

SealAsync(byte[], string, IAesGcmCipher?, CancellationToken)

Seal a preimage to covclaimd's public key.

public static Task<SealedClaimPacket> SealAsync(byte[] preimage, string covclaimdPubKeyHex, IAesGcmCipher? cipher = null, CancellationToken cancellationToken = default)

Parameters

preimage byte[]

The 32-byte secret the client chose.

covclaimdPubKeyHex string

covclaimd's compressed secp256k1 key, from GET /v1/preimage/covclaimd-pubkey. Read it live — covclaimd generates its own, so a hardcoded value goes stale silently.

cipher IAesGcmCipher

Supplies AES-GCM. Defaults to the platform's, which is right everywhere except a browser — see IAesGcmCipher.

cancellationToken CancellationToken

Cancels the encryption.

Returns

Task<SealedClaimPacket>

The packet, the preimage and its payment hash.

Remarks

The ECDH shared secret is the 32-byte X coordinate, not the 33-byte compressed point. Keeping the parity byte still yields a well-formed key on both sides, so nothing local disagrees — only the remote AEAD tag check fails, and only once a live daemon sees it. The same trap exists in the JS reference, whose ECDH helper returns the compressed point by default.