Skip to content

Feat/sep43 sign auth entry#50

Merged
wantedsystem merged 6 commits intomainfrom
feat/sep43-sign-auth-entry
May 6, 2026
Merged

Feat/sep43 sign auth entry#50
wantedsystem merged 6 commits intomainfrom
feat/sep43-sign-auth-entry

Conversation

@wantedsystem
Copy link
Copy Markdown
Contributor

@wantedsystem wantedsystem commented May 4, 2026

Explanation

Adds the third SEP-43 method, stellar_signAuthEntry, to the snap. Dapps can now request the user to sign a Soroban authorization entry (HashIdPreimage with envelopeTypeSorobanAuthorization) — the lower-level primitive used for pre-authorizing contract invocations and custom-account auth flows. Behavior matches signMessage / signTransaction:

  • Exposed via onRpcRequest (stellar_signAuthEntry) and via the keyring submitRequest route.
  • Origin permission enforced through validateOrigin.
  • Mainnet-only: rejects non-mainnet scope or opts.networkPassphrase with -3.
  • Confirmation dialog (ConfirmSignAuthEntry) renders contract, function, expiration ledger, nonce, optional nested-authorizations count, origin, account, and network, with a warning that the user is authorizing a contract to act on their behalf.
  • On confirm: returns { signedAuthEntry: <base64>, signerAddress } (SHA-256 of the raw HashIdPreimage bytes, signed Ed25519 — no SEP-53 message prefix).
  • On reject: returns { signedAuthEntry: '', signerAddress, error: { code: -4 } }.
  • Invalid input (bad base64, non-Soroban-auth preimage, forbidden opts.submit, wrong network) returns { ..., error: { code: -3 } }.

Test plan (QA)

Setup:

  • Run yarn start, open the test dapp at http://localhost:8000, connect MetaMask Flask, install the snap.
  • Make sure the connected account is a mainnet (stellar:pubnet) account.

1. Happy path — confirm

  1. In the test dapp, click the Sign auth entry button.

  2. Paste this XDR (valid HashIdPreimage, mainnet, transfer, no sub-invocations):
    AAAACXrDOZdUTjF10ma9AiQ5sizbFlCMARY/JuXLKj4QRal5AAAAAAdbzRUAD0JAAAAAAAAAAAECAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgAAAAh0cmFuc2ZlcgAAAAAAAAAA

  3. Expect dialog:

    • Title: Authorize smart contract
    • Yellow warning: You are authorizing a smart contract to act on your behalf…
    • Contract: CAAQCAI…QC526
    • Function: transfer
    • Expires at ledger: 1000000
    • Nonce: 123456789
    • Request from: localhost
    • Account: connected account
    • Network: Mainnet
    • No "Nested authorizations" row.
Screenshot 2026-05-04 at 15 50 12
  1. Click Confirm.
  2. Expected dapp response :
    { "signedAuthEntry": "<non-empty base64>", "signerAddress": "<G…>" }

2. User rejects

  1. Repeat step 1 but click Cancel.
  2. Expect dapp response:
{
  "signedAuthEntry": "",
  "signerAddress": "<G…>",
  "error": { "code": -4, "message": "User rejected the request." 
}

Errors to encounter (QA)

Generate / inspect HashIdPreimage XDR with Stellar Lab → XDR → View XDR (set the type to HashIDPreimage).

Screenshot 2026-05-04 at 16 53 16

These all share the same dapp-side response shape — signedAuthEntry: '', signerAddress: '<G…>' or '', error: { code, message, ext? } — and none should display the confirmation dialog (except case 7, user rejection).

# Scenario Trigger Expected error
1 Invalid base64 Call with authEntry: "not-base64" code: -3, ext references request.params.authEntry.
2 Wrong preimage type Pass a valid base64 XDR whose discriminant isn't envelopeTypeSorobanAuthorization (e.g. paste a signTransaction envelope XDR into the authEntry field). code: -3, ext includes HashIdPreimage is not a Soroban authorization preimage.
3 Non-mainnet scope Issue the keyring request with scope: "stellar:testnet" (use the dapp's testnet toggle, or the snap-shell). code: -3.
4 Wrong opts.networkPassphrase Valid mainnet XDR + opts: { networkPassphrase: "Test SDF Network ; September 2015" }. code: -3, ext mentions mainnet.
5 Forbidden opts.submit Valid XDR + opts: { submit: true } (the snap is sign-only, never submits). code: -3.
6 Forbidden opts.submitUrl Valid XDR + opts: { submitUrl: "https://horizon.stellar.org" }. code: -3.
7 User rejects Valid XDR; click Cancel in the confirmation dialog. code: -4 (User rejected the request). The dialog does appear here — only error case where it should.

Edge cases (no error)

# Scenario Trigger Expected behavior
8 opts.address is informational Valid XDR + opts: { address: <other funded account in same wallet> }. Dialog opens for the connected account (snap ignores opts.address); response signerAddress matches the connected account.
9 UTF-8 vs base64 in authEntry N/A — authEntry is always a base64 XDR, never UTF-8. Plain UTF-8 will hit case 1 (-3), which is correct. Mention this only so QA knows not to file a bug.

You can generate XDR from JSON using this tool Stellar Lab → XDR → JSON to XDR

References

Checklist

  • I've updated the test suite for new or updated code as appropriate
  • I've updated documentation (JSDoc, Markdown, etc.) for new or updated code as appropriate
  • I've communicated my changes to consumers by updating changelogs for packages I've changed
  • I've introduced breaking changes in this PR and have prepared draft pull requests for clients and consumer packages to resolve them

@wantedsystem wantedsystem requested a review from a team as a code owner May 4, 2026 14:44
@wantedsystem wantedsystem requested a review from Copilot May 4, 2026 15:14
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds SEP-43 signAuthEntry support to the Stellar snap, enabling dapps (and the local dev dapp) to request signatures over Soroban authorization entry preimages (HashIdPreimage with envelopeTypeSorobanAuthorization) with a dedicated confirmation UX.

Changes:

  • Introduces a new SEP-43 keyring handler (signAuthEntry) with request/response validation, decoding for user display, and Ed25519 signing of sha256(preimageBytes).
  • Adds a new confirmation dialog view (ConfirmSignAuthEntry) and wires it into the confirmation controller + user input event handlers.
  • Updates keyring method registration, account capability metadata, dev-only RPC routing, and extends unit test coverage across wallet/keyring/api layers.

Reviewed changes

Copilot reviewed 25 out of 25 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
packages/snap/src/ui/confirmation/views/ConfirmSignAuthEntry/events.tsx Adds confirm/cancel UI event handlers for the new auth-entry confirmation dialog.
packages/snap/src/ui/confirmation/views/ConfirmSignAuthEntry/ConfirmSignAuthEntry.tsx Implements the confirmation UI rendering Soroban auth-entry summary and signer/origin/network details.
packages/snap/src/ui/confirmation/controller.tsx Wires new SignAuthEntry interface key to the corresponding confirmation view.
packages/snap/src/ui/confirmation/api.ts Adds ConfirmationInterfaceKey.SignAuthEntry.
packages/snap/src/services/wallet/Wallet.ts Adds Wallet.signAuthEntry that hashes preimage bytes and signs the digest (no SEP-53 prefix).
packages/snap/src/services/wallet/Wallet.test.ts Adds unit tests verifying signAuthEntry hashing/signature behavior and encodings.
packages/snap/src/services/wallet/exceptions.ts Adds SignAuthEntryException.
packages/snap/src/services/account/AccountService.ts Advertises signAuthEntry as a supported method on Stellar accounts.
packages/snap/src/services/account/AccountService.test.ts Updates expected supported methods to include signAuthEntry.
packages/snap/src/index.ts Adds dev-only RPC alias stellar_signAuthEntry routing to the handler.
packages/snap/src/handlers/user-input/userInput.ts Registers auth-entry confirmation UI event handlers with the user-input handler.
packages/snap/src/handlers/keyring/signAuthEntry.ts Introduces the SEP-43 signAuthEntry keyring handler and Soroban preimage decoding for UI.
packages/snap/src/handlers/keyring/signAuthEntry.test.ts Adds handler tests for confirm/reject and invalid-request scenarios.
packages/snap/src/handlers/keyring/keyring.test.ts Adds keyring submitRequest coverage for signAuthEntry routing and response validation.
packages/snap/src/handlers/keyring/index.ts Exports the new handler module.
packages/snap/src/handlers/keyring/base.ts Updates base handler docstring to include SignAuthEntry.
packages/snap/src/handlers/keyring/api.ts Adds new method enum value + request/response superstructs for signAuthEntry.
packages/snap/src/handlers/keyring/api.test.ts Adds superstruct validation tests for signAuthEntry request/response envelopes.
packages/snap/src/context.ts Instantiates and registers SignAuthEntryHandler in the handler map and exports it.
packages/snap/src/api/xdr.ts Adds HashIdPreimageXdrStruct validation for Soroban authorization preimages.
packages/snap/snap.manifest.json Updates the bundle shasum for the new build output.
packages/snap/messages.json Adds i18n strings for the new auth-entry confirmation dialog.
packages/snap/locales/es.json Adds locale entries for the new auth-entry confirmation dialog.
packages/snap/locales/en.json Adds locale entries for the new auth-entry confirmation dialog.
packages/site/src/pages/index.tsx Extends the local dev dapp UI to call stellar_signAuthEntry and display responses.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread packages/snap/src/api/xdr.ts
Copy link
Copy Markdown
Collaborator

@stanleyyconsensys stanleyyconsensys left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for the work
LGTM! just few nits comment

in addition.
i like the PR has so many details, i think i will try to do the same
but since QA will not visit this PR

lets move them to sub task that you are doing, and pick some important step/information into story

Comment thread packages/snap/src/services/wallet/Wallet.test.ts Outdated
Comment thread packages/snap/src/api/xdr.ts Outdated
<SnapText>{nonce}</SnapText>
</Box>

{subInvocationsCount > 0 ? (
Copy link
Copy Markdown
Collaborator

@stanleyyconsensys stanleyyconsensys May 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shall we follow freighter wallet for the information that we display (no need 100%)
https://github.com/stellar/freighter/blob/1ee0e0c8141167021d597c1d4786bee3d75e5124/extension/src/popup/views/SignAuthEntry/index.tsx#L272

And i do think auth entry is a good info to display

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done you can test with this XDR AAAACXrDOZdUTjF10ma9AiQ5sizbFlCMARY/JuXLKj4QRal5AAAAADreaLEATEtAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAh0cmFuc2ZlcgAAAAIAAAASAAAAAAAAAAAXmJXrnYi/8w2mnLPffCyumwfXR1G+1z2CgWGZvcdM9AAAAAoAAAAAAAAAAAAAAAAAD0JAAAAAAQAAAAAAAAABAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAAAAHYXBwcm92ZQAAAAACAAAAEgAAAAAAAAAAqWUiKUM8kOWf3SM9URxLuIgw/VPfd7r+pRiXkHzR8NQAAAADAAAD6AAAAAA=

): Promise<string> {
try {
const preimageBuffer = bufferToUint8Array(authEntry, 'base64');
const preimageHash = await sha256(preimageBuffer);
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sorry, i miss the review here, may i ask why we need sha256?

because only SEP53 require signMessage to have sha256 (becoz it need to combine the prefix)

Stellar official site recommend reference
https://github.com/stellar/js-stellar-base/blob/e3d6fc3351e7d242b374c7c6057668366364a279/src/auth.js#L97

Feligher wallet reference
https://github.com/stellar/freighter/blob/b19a3b899f2273f022421924f4d423ccd0058dcb/extension/src/background/messageListener/handlers/signAuthEntry.ts#L63

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey good question, sha256 is actually required here. Both references you linked do the same thing:

Btw hash() in stellar-sdk is sha256 — see @stellar/stellar-base/src/hashing.js

function hash(data) {
  var hasher = new sha256();
  hasher.update(data, 'utf8');
  return hasher.digest();
}

Same digest, different name. We're using sha256 directly
The Soroban host verifies signatures against sha256(preimage), so without the hash step our signatures wouldn't verify on-chain. Different reason from the SEP-53 prefix in signMessage, but both end up needing sha256.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shall we use this hash function instead then?

const { contractAddress, functionName, args, subInvocations } = invocation;

return (
<Box direction="vertical">
Copy link
Copy Markdown
Collaborator

@stanleyyconsensys stanleyyconsensys May 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • lets move the section for "request from, network..." on the top, and the innovation detail at bottom to align the other dialog (i think we do the same for txn as well)
  • lets follow the similar structure as freighter
    • no need nonce, expired...
    • align label
Image

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will reorder to match Freighter

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like this now :
Screenshot 2026-05-06 at 11 11 44

@wantedsystem wantedsystem merged commit a35ea9e into main May 6, 2026
10 checks passed
@wantedsystem wantedsystem deleted the feat/sep43-sign-auth-entry branch May 6, 2026 09:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants