Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,16 @@ jobs:
if: steps.bindings.outcome == 'success'
run: git diff --exit-code
working-directory: .
# ABI extraction depends on the same soroban-sdk 22 WASM build as above.
# When the SDK bump (23.x/27.x) lands, remove continue-on-error to
# enforce ABI snapshot freshness on every PR.
- name: Extract ABI snapshots
id: abi
continue-on-error: true
run: ./abi/update.sh
- name: Check ABI snapshots
if: steps.abi.outcome == 'success'
run: git diff --exit-code abi/

stellar-nightly:
if: github.event_name == 'schedule'
Expand Down Expand Up @@ -222,7 +232,6 @@ jobs:
path: |
stellar/deploy-dryrun-output.txt
stellar/contract-ids.txt

solana:
needs: changes
if: needs.changes.outputs.solana == 'true'
Expand Down
15 changes: 15 additions & 0 deletions stellar/abi/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Stellar Contract ABI Snapshots

This directory contains JSON snapshots of the Soroban contract ABIs. These snapshots serve as a CI gate to prevent unintentional or silent breaking changes to contract interfaces (such as function signatures, error variants, or event topics) that downstream indexers and SDKs rely on.

## Updating the ABI

If your PR intentionally modifies a contract's interface, you must update the snapshots. Otherwise, the CI job will fail.

To update the ABI snapshots, run the update script from the `stellar` directory:

```bash
./abi/update.sh
```

This will compile the contracts and overwrite the `.json` snapshots in this directory. Make sure to commit the updated snapshots in your PR.
35 changes: 35 additions & 0 deletions stellar/abi/stealth_announcer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
[
{
"function_v0": {
"doc": "Emits a stealth address announcement event.\\n\\nThis is a pure event-emission function with no access control and no\\nstorage. Indexers watch for these events to let recipients detect\\nincoming payments.\\n\\n# Arguments\\n* `scheme_id` - Identifier for the stealth address scheme (e.g. 1 for the default DKSAP scheme).\\n* `stealth_address` - The one-time stealth address that received funds.\\n* `ephemeral_pub_key` - The ephemeral public key used to derive the stealth address.\\n* `metadata` - Arbitrary metadata (e.g. view tag) to speed up scanning.",
"name": "announce",
"inputs": [
{
"doc": "",
"name": "scheme_id",
"type_": "u32"
},
{
"doc": "",
"name": "stealth_address",
"type_": "address"
},
{
"doc": "",
"name": "ephemeral_pub_key",
"type_": {
"bytes_n": {
"n": 32
}
}
},
{
"doc": "",
"name": "metadata",
"type_": "bytes"
}
],
"outputs": []
}
}
]
109 changes: 109 additions & 0 deletions stellar/abi/stealth_registry.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
[
{
"udt_union_v0": {
"doc": "Storage keys.",
"lib": "",
"name": "DataKey",
"cases": [
{
"tuple_v0": {
"doc": "Maps (registrant, scheme_id) to their stealth meta-address (64 bytes:\\nspending_pubkey || viewing_pubkey).",
"name": "MetaAddress",
"type_": [
"address",
"u32"
]
}
}
]
}
},
{
"function_v0": {
"doc": "Register or update a stealth meta-address.\\n\\n# Arguments\\n* `registrant` - The address whose meta-address is being set (must authorise).\\n* `scheme_id` - The stealth address scheme identifier.\\n* `stealth_meta_address` - 64-byte value: `spending_pubkey || viewing_pubkey`.",
"name": "register_keys",
"inputs": [
{
"doc": "",
"name": "registrant",
"type_": "address"
},
{
"doc": "",
"name": "scheme_id",
"type_": "u32"
},
{
"doc": "",
"name": "stealth_meta_address",
"type_": "bytes"
}
],
"outputs": [
{
"result": {
"ok_type": {
"tuple": {
"value_types": []
}
},
"error_type": {
"udt": {
"name": "RegistryError"
}
}
}
}
]
}
},
{
"udt_error_enum_v0": {
"doc": "Errors that the registry can produce.",
"lib": "",
"name": "RegistryError",
"cases": [
{
"doc": "The supplied stealth meta-address is not exactly 64 bytes.",
"name": "InvalidMetaAddressLength",
"value": 1
},
{
"doc": "No stealth meta-address has been registered for the given address and scheme.",
"name": "NotRegistered",
"value": 2
}
]
}
},
{
"function_v0": {
"doc": "Look up a previously registered stealth meta-address.\\n\\n# Arguments\\n* `registrant` - The address to look up.\\n* `scheme_id` - The stealth address scheme identifier.",
"name": "stealth_meta_address_of",
"inputs": [
{
"doc": "",
"name": "registrant",
"type_": "address"
},
{
"doc": "",
"name": "scheme_id",
"type_": "u32"
}
],
"outputs": [
{
"result": {
"ok_type": "bytes",
"error_type": {
"udt": {
"name": "RegistryError"
}
}
}
}
]
}
}
]
212 changes: 212 additions & 0 deletions stellar/abi/stealth_sender.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
[
{
"function_v0": {
"doc": "Initialise the contract by storing the announcer address.\\n\\nMust be called exactly once before any `send` or `batch_send`.",
"name": "init",
"inputs": [
{
"doc": "",
"name": "announcer",
"type_": "address"
}
],
"outputs": [
{
"result": {
"ok_type": {
"tuple": {
"value_types": []
}
},
"error_type": {
"udt": {
"name": "SenderError"
}
}
}
}
]
}
},
{
"function_v0": {
"doc": "Transfer tokens to a stealth address and emit an announcement.\\n\\n# Arguments\\n* `sender` - The address sending funds (must authorise).\\n* `token` - SAC token contract address (works for native XLM too).\\n* `amount` - Amount of tokens to transfer.\\n* `scheme_id` - Stealth address scheme identifier.\\n* `stealth_address` - The derived one-time stealth address.\\n* `ephemeral_pub_key` - Ephemeral public key for the recipient to scan.\\n* `metadata` - Extra data (e.g. view tag).",
"name": "send",
"inputs": [
{
"doc": "",
"name": "sender",
"type_": "address"
},
{
"doc": "",
"name": "token",
"type_": "address"
},
{
"doc": "",
"name": "amount",
"type_": "i128"
},
{
"doc": "",
"name": "scheme_id",
"type_": "u32"
},
{
"doc": "",
"name": "stealth_address",
"type_": "address"
},
{
"doc": "",
"name": "ephemeral_pub_key",
"type_": {
"bytes_n": {
"n": 32
}
}
},
{
"doc": "",
"name": "metadata",
"type_": "bytes"
}
],
"outputs": [
{
"result": {
"ok_type": {
"tuple": {
"value_types": []
}
},
"error_type": {
"udt": {
"name": "SenderError"
}
}
}
}
]
}
},
{
"udt_union_v0": {
"doc": "Storage keys.",
"lib": "",
"name": "DataKey",
"cases": [
{
"void_v0": {
"doc": "The address of the deployed StealthAnnouncer contract.",
"name": "Announcer"
}
}
]
}
},
{
"function_v0": {
"doc": "Batch version of `send` \\xe2\\x80\\x94 transfers tokens to multiple stealth addresses\\nand emits an announcement for each.\\n\\nAll input vectors must have the same length.",
"name": "batch_send",
"inputs": [
{
"doc": "",
"name": "sender",
"type_": "address"
},
{
"doc": "",
"name": "token",
"type_": "address"
},
{
"doc": "",
"name": "scheme_id",
"type_": "u32"
},
{
"doc": "",
"name": "stealth_addresses",
"type_": {
"vec": {
"element_type": "address"
}
}
},
{
"doc": "",
"name": "ephemeral_pub_keys",
"type_": {
"vec": {
"element_type": {
"bytes_n": {
"n": 32
}
}
}
}
},
{
"doc": "",
"name": "metadatas",
"type_": {
"vec": {
"element_type": "bytes"
}
}
},
{
"doc": "",
"name": "amounts",
"type_": {
"vec": {
"element_type": "i128"
}
}
}
],
"outputs": [
{
"result": {
"ok_type": {
"tuple": {
"value_types": []
}
},
"error_type": {
"udt": {
"name": "SenderError"
}
}
}
}
]
}
},
{
"udt_error_enum_v0": {
"doc": "Errors that the sender contract can produce.",
"lib": "",
"name": "SenderError",
"cases": [
{
"doc": "The contract has already been initialised.",
"name": "AlreadyInitialized",
"value": 1
},
{
"doc": "The contract has not been initialised yet.",
"name": "NotInitialized",
"value": 2
},
{
"doc": "The batch input vectors have mismatched lengths.",
"name": "LengthMismatch",
"value": 3
}
]
}
}
]
Loading
Loading