signAuthEntry

suspend fun signAuthEntry(entry: SorobanAuthorizationEntryXdr, signer: SmartAccountSigner, signature: SmartAccountSignature, expirationLedger: UInt, contextRuleIds: List<UInt> = emptyList()): SorobanAuthorizationEntryXdr

Attaches a pre-computed signature to an authorization entry.

This method does NOT perform cryptographic signing. The caller is responsible for computing the signature over the correct payload hash. Use buildAuthPayloadHash with the same expirationLedger value to obtain the hash before calling this method.

Attaching the signature involves the following steps:

  1. Clones the entry via XDR round-trip (encode then decode)

  2. Sets the signature expiration ledger on the credentials

  3. Builds the signer key ScVal from the signer

  4. Double XDR-encodes the signature value (CRITICAL)

  5. Creates a map entry with key=signer, value=double-encoded-signature

  6. Merges with any existing signatures (multi-signer accumulation)

  7. Sorts map entries by XDR-encoded key bytes (lowercase hex, lexicographic)

  8. Returns the entry with the updated signature map

CRITICAL DETAILS:

  • The input entry is never mutated; a deep clone is returned

  • Signature value uses DOUBLE XDR encoding: encode the ScVal to bytes, then wrap those bytes in a new ScVal::Bytes

  • Map entries MUST be sorted by their XDR-encoded key bytes as lowercase hex

  • Credentials must be of type .Address

The signature map format is:

ScVal::Vec([
ScVal::Map([
{ key: signer.toScVal(), value: ScVal::Bytes(XDR_encode(signatureScVal)) },
...
])
])

Return

A new authorization entry with the signature attached

Parameters

entry

The authorization entry to attach the signature to

signer

The Smart Account signer (delegated or external)

signature

The pre-computed signature object (WebAuthn, Ed25519, or Policy)

expirationLedger

The ledger number at which the signature expires. Must match the value passed to buildAuthPayloadHash when producing the signature.

Throws

if credentials is not .Address type, if XDR encoding/decoding fails, or if map construction fails

Example:

val expirationLedger = currentLedger + 100u
val payloadHash = SmartAccountAuth.buildAuthPayloadHash(
entry = unsignedEntry,
expirationLedger = expirationLedger,
networkPassphrase = Network.TESTNET.networkPassphrase
)
val webAuthnSig = WebAuthnSignature(
authenticatorData = authData,
clientData = clientData,
signature = signOverPayloadHash(payloadHash)
)
val signedEntry = SmartAccountAuth.signAuthEntry(
entry = unsignedEntry,
signer = externalSigner,
signature = webAuthnSig,
expirationLedger = expirationLedger
)