Skip to content
Draft
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
/libdocs/
/dist/
/coverage/
*.tgz
/jsdoc/
/.astro/

Expand Down
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@ A breaking change will get clearly marked in this log.

## Unreleased

### Added
- Protocol 28 (CAP-0084): muxed contract addresses. The vendored XDR now
includes the `SC_ADDRESS_TYPE_MUXED_CONTRACT` arm and `MuxedContract` struct,
and `Address` gains `Address.muxedContract(contractId, id)` plus
`contractId()` / `muxedId()` accessors. These addresses have no canonical
StrKey yet, so they round-trip via `ScAddress`/`ScVal` (not via a string);
`toString()` renders the display-only `<C-strkey>:<id>` form.

## [v16.0.1](https://github.com/stellar/js-stellar-sdk/compare/v16.0.0...v16.0.1)

### Fixed
Expand Down
25 changes: 17 additions & 8 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
XDR_BASE_URL_CURR=https://github.com/stellar/stellar-xdr/raw/68fa1ac55692f68ad2a2ca549d0a283273554439
# CAP-83 + CAP-84 pre-release: pin to the protocol-28 .x and resolve
# feature gates via `stellar-xdr xfile preprocess` (rs-stellar-xdr #503) before
# xdrgen, since the Ruby xdrgen used here does not understand #ifdef.
# CAP_0084_MUXED_CONTRACT is gated to the `next` channel only: the muxed
# contract address arm is not enabled on `curr` until protocol 28 ships.
XDR_BASE_URL_CURR=https://github.com/stellar/stellar-xdr/raw/787382ef2099cca168ca1cb282730d6b7b9e2f16
XDR_BASE_LOCAL_CURR=xdr/curr
XDR_FEATURES_CURR=CAP_0083
XDR_FEATURES_NEXT=CAP_0083,CAP_0084_MUXED_CONTRACT
XDR_FILES_CURR= \
Stellar-SCP.x \
Stellar-ledger-entries.x \
Expand All @@ -15,7 +22,7 @@ XDR_FILES_CURR= \
Stellar-exporter.x
XDR_FILES_LOCAL_CURR=$(addprefix xdr/curr/,$(XDR_FILES_CURR))

XDR_BASE_URL_NEXT=https://github.com/stellar/stellar-xdr/raw/68fa1ac55692f68ad2a2ca549d0a283273554439
XDR_BASE_URL_NEXT=https://github.com/stellar/stellar-xdr/raw/787382ef2099cca168ca1cb282730d6b7b9e2f16
XDR_BASE_LOCAL_NEXT=xdr/next
XDR_FILES_NEXT= \
Stellar-SCP.x \
Expand Down Expand Up @@ -43,23 +50,25 @@ generate: src/base/generated/curr_generated.js src/base/generated/curr.d.ts src/
src/base/generated/curr_generated.js: $(XDR_FILES_LOCAL_CURR)
mkdir -p $(dir $@)
> $@
docker run -it --rm -v $$PWD:/wd -w /wd ruby:3.1 /bin/bash -c '\
docker run --rm -v $$PWD:/wd -w /wd ruby:3.1 /bin/bash -c '\
gem install specific_install -v 0.3.8 && \
gem specific_install https://github.com/stellar/xdrgen.git -b $(XDRGEN_COMMIT) && \
xdrgen --language javascript --namespace curr --output src/base/generated $^ \
'
python3 scripts/post-process-generated.py $@

src/base/generated/next_generated.js: $(XDR_FILES_LOCAL_NEXT)
mkdir -p $(dir $@)
> $@
docker run -it --rm -v $$PWD:/wd -w /wd ruby:3.1 /bin/bash -c '\
docker run --rm -v $$PWD:/wd -w /wd ruby:3.1 /bin/bash -c '\
gem install specific_install -v 0.3.8 && \
gem specific_install https://github.com/stellar/xdrgen.git -b $(XDRGEN_COMMIT) && \
xdrgen --language javascript --namespace next --output src/base/generated $^ \
'
python3 scripts/post-process-generated.py $@

src/base/generated/curr.d.ts: src/base/generated/curr_generated.js
docker run -it --rm -v $$PWD:/wd -w / --entrypoint /bin/sh node:22-alpine -c '\
docker run --rm -v $$PWD:/wd -w / --entrypoint /bin/sh node:22-alpine -c '\
apk add --update git && \
corepack enable && \
corepack prepare pnpm@$(PNPM_VERSION) --activate && \
Expand All @@ -73,7 +82,7 @@ src/base/generated/curr.d.ts: src/base/generated/curr_generated.js
'

src/base/generated/next.d.ts: src/base/generated/next_generated.js
docker run -it --rm -v $$PWD:/wd -w / --entrypoint /bin/sh node:22-alpine -c '\
docker run --rm -v $$PWD:/wd -w / --entrypoint /bin/sh node:22-alpine -c '\
apk add --update git && \
corepack enable && \
corepack prepare pnpm@$(PNPM_VERSION) --activate && \
Expand All @@ -92,12 +101,12 @@ clean:
$(XDR_FILES_LOCAL_CURR):
mkdir -p $(dir $@)
curl -L -o $@ $(XDR_BASE_URL_CURR)/$(notdir $@)
stellar-xdr xfile preprocess --features "$(XDR_FEATURES)" $@ > $@.pp && mv -f $@.pp $@
stellar-xdr xfile preprocess --features "$(XDR_FEATURES_CURR)" $@ > $@.pp && mv -f $@.pp $@

$(XDR_FILES_LOCAL_NEXT):
mkdir -p $(dir $@)
curl -L -o $@ $(XDR_BASE_URL_NEXT)/$(notdir $@)
stellar-xdr xfile preprocess --features "$(XDR_FEATURES)" $@ > $@.pp && mv -f $@.pp $@
stellar-xdr xfile preprocess --features "$(XDR_FEATURES_NEXT)" $@ > $@.pp && mv -f $@.pp $@
reset-xdr:
rm -f xdr/*/*.x
rm -f src/base/generated/*.js
Expand Down
90 changes: 75 additions & 15 deletions docs/reference/core-soroban-primitives.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,18 @@ class Address {
static fromString(address: string): Address;
static liquidityPool(buffer: Buffer): Address;
static muxedAccount(buffer: Buffer): Address;
static muxedContract(contractId: Buffer, id: string | number | bigint | Uint64): Address;
readonly type: AddressType;
contractId(): Buffer;
muxedId(): Uint64;
toBuffer(): Buffer;
toScAddress(): ScAddress;
toScVal(): ScVal;
toString(): string;
}
```

**Source:** [src/base/address.ts:20](https://github.com/stellar/js-stellar-sdk/blob/main/src/base/address.ts#L20)
**Source:** [src/base/address.ts:25](https://github.com/stellar/js-stellar-sdk/blob/main/src/base/address.ts#L25)

### `new Address(address)`

Expand All @@ -38,7 +41,7 @@ constructor(address: string);

- **`address`** — `string` (required) — a `StrKey` of the address value

**Source:** [src/base/address.ts:27](https://github.com/stellar/js-stellar-sdk/blob/main/src/base/address.ts#L27)
**Source:** [src/base/address.ts:35](https://github.com/stellar/js-stellar-sdk/blob/main/src/base/address.ts#L35)

### `Address.account(buffer)`

Expand All @@ -52,7 +55,7 @@ static account(buffer: Buffer): Address;

- **`buffer`** — `Buffer` (required) — The bytes of an address to parse.

**Source:** [src/base/address.ts:62](https://github.com/stellar/js-stellar-sdk/blob/main/src/base/address.ts#L62)
**Source:** [src/base/address.ts:70](https://github.com/stellar/js-stellar-sdk/blob/main/src/base/address.ts#L70)

### `Address.claimableBalance(buffer)`

Expand All @@ -66,7 +69,7 @@ static claimableBalance(buffer: Buffer): Address;

- **`buffer`** — `Buffer` (required) — The bytes of a claimable balance ID to parse.

**Source:** [src/base/address.ts:80](https://github.com/stellar/js-stellar-sdk/blob/main/src/base/address.ts#L80)
**Source:** [src/base/address.ts:88](https://github.com/stellar/js-stellar-sdk/blob/main/src/base/address.ts#L88)

### `Address.contract(buffer)`

Expand All @@ -80,7 +83,7 @@ static contract(buffer: Buffer): Address;

- **`buffer`** — `Buffer` (required) — The bytes of an address to parse.

**Source:** [src/base/address.ts:71](https://github.com/stellar/js-stellar-sdk/blob/main/src/base/address.ts#L71)
**Source:** [src/base/address.ts:79](https://github.com/stellar/js-stellar-sdk/blob/main/src/base/address.ts#L79)

### `Address.fromScAddress(scAddress)`

Expand All @@ -94,7 +97,7 @@ static fromScAddress(scAddress: ScAddress): Address;

- **`scAddress`** — `ScAddress` (required) — The xdr.ScAddress type to parse

**Source:** [src/base/address.ts:116](https://github.com/stellar/js-stellar-sdk/blob/main/src/base/address.ts#L116)
**Source:** [src/base/address.ts:150](https://github.com/stellar/js-stellar-sdk/blob/main/src/base/address.ts#L150)

### `Address.fromScVal(scVal)`

Expand All @@ -108,7 +111,7 @@ static fromScVal(scVal: ScVal): Address;

- **`scVal`** — `ScVal` (required) — The xdr.ScVal type to parse

**Source:** [src/base/address.ts:107](https://github.com/stellar/js-stellar-sdk/blob/main/src/base/address.ts#L107)
**Source:** [src/base/address.ts:141](https://github.com/stellar/js-stellar-sdk/blob/main/src/base/address.ts#L141)

### `Address.fromString(address)`

Expand All @@ -122,7 +125,7 @@ static fromString(address: string): Address;

- **`address`** — `string` (required) — The address to parse. ex. `GB3KJPLFUYN5VL6R3GU3EGCGVCKFDSD7BEDX42HWG5BWFKB3KQGJJRMA`

**Source:** [src/base/address.ts:53](https://github.com/stellar/js-stellar-sdk/blob/main/src/base/address.ts#L53)
**Source:** [src/base/address.ts:61](https://github.com/stellar/js-stellar-sdk/blob/main/src/base/address.ts#L61)

### `Address.liquidityPool(buffer)`

Expand All @@ -136,7 +139,7 @@ static liquidityPool(buffer: Buffer): Address;

- **`buffer`** — `Buffer` (required) — The bytes of an LP ID to parse.

**Source:** [src/base/address.ts:89](https://github.com/stellar/js-stellar-sdk/blob/main/src/base/address.ts#L89)
**Source:** [src/base/address.ts:97](https://github.com/stellar/js-stellar-sdk/blob/main/src/base/address.ts#L97)

### `Address.muxedAccount(buffer)`

Expand All @@ -150,7 +153,31 @@ static muxedAccount(buffer: Buffer): Address;

- **`buffer`** — `Buffer` (required) — The bytes of an address to parse.

**Source:** [src/base/address.ts:98](https://github.com/stellar/js-stellar-sdk/blob/main/src/base/address.ts#L98)
**Source:** [src/base/address.ts:106](https://github.com/stellar/js-stellar-sdk/blob/main/src/base/address.ts#L106)

### `Address.muxedContract(contractId, id)`

Creates a new muxed-contract Address object (CAP-0084).

A muxed-contract address (`SC_ADDRESS_TYPE_MUXED_CONTRACT`) pairs a
32-byte contract ID with a `uint64` multiplexing ID. There is no canonical
StrKey form for it yet, so unlike the other factories it does not route
through the `Address` constructor and the resulting address cannot be
parsed back out of a string. Round-trip it through
`Address.fromScAddress` / `Address#toScAddress` instead;
`Address#toString` renders the display-only form `<C-strkey>:<id>`.

```ts
static muxedContract(contractId: Buffer, id: string | number | bigint | Uint64): Address;
```

**Parameters**

- **`contractId`** — `Buffer` (required) — the raw 32 bytes of the contract ID
- **`id`** — `string | number | bigint | Uint64` (required) — the uint64 multiplexing ID; pass a string or `xdr.Uint64`
for values above `Number.MAX_SAFE_INTEGER` to avoid precision loss

**Source:** [src/base/address.ts:125](https://github.com/stellar/js-stellar-sdk/blob/main/src/base/address.ts#L125)

### `address.type`

Expand All @@ -160,7 +187,35 @@ Return the type of this address.
readonly type: AddressType;
```

**Source:** [src/base/address.ts:219](https://github.com/stellar/js-stellar-sdk/blob/main/src/base/address.ts#L219)
**Source:** [src/base/address.ts:310](https://github.com/stellar/js-stellar-sdk/blob/main/src/base/address.ts#L310)

### `address.contractId()`

For a muxed-contract address, returns the raw 32-byte contract ID.

```ts
contractId(): Buffer;
```

**Throws**

- if this is not a muxed-contract address

**Source:** [src/base/address.ts:286](https://github.com/stellar/js-stellar-sdk/blob/main/src/base/address.ts#L286)

### `address.muxedId()`

For a muxed-contract address, returns the `uint64` multiplexing ID.

```ts
muxedId(): Uint64;
```

**Throws**

- if this is not a muxed-contract address

**Source:** [src/base/address.ts:300](https://github.com/stellar/js-stellar-sdk/blob/main/src/base/address.ts#L300)

### `address.toBuffer()`

Expand All @@ -170,7 +225,12 @@ Return the raw public key bytes for this address.
toBuffer(): Buffer;
```

**Source:** [src/base/address.ts:212](https://github.com/stellar/js-stellar-sdk/blob/main/src/base/address.ts#L212)
**Throws**

- for muxed-contract addresses, which have no single-buffer encoding
(use `Address#contractId` / `Address#muxedId`)

**Source:** [src/base/address.ts:274](https://github.com/stellar/js-stellar-sdk/blob/main/src/base/address.ts#L274)

### `address.toScAddress()`

Expand All @@ -180,7 +240,7 @@ Convert this Address to an xdr.ScAddress type.
toScAddress(): ScAddress;
```

**Source:** [src/base/address.ts:174](https://github.com/stellar/js-stellar-sdk/blob/main/src/base/address.ts#L174)
**Source:** [src/base/address.ts:224](https://github.com/stellar/js-stellar-sdk/blob/main/src/base/address.ts#L224)

### `address.toScVal()`

Expand All @@ -190,7 +250,7 @@ Convert this Address to an xdr.ScVal type.
toScVal(): ScVal;
```

**Source:** [src/base/address.ts:167](https://github.com/stellar/js-stellar-sdk/blob/main/src/base/address.ts#L167)
**Source:** [src/base/address.ts:217](https://github.com/stellar/js-stellar-sdk/blob/main/src/base/address.ts#L217)

### `address.toString()`

Expand All @@ -200,7 +260,7 @@ Serialize an address to string.
toString(): string;
```

**Source:** [src/base/address.ts:147](https://github.com/stellar/js-stellar-sdk/blob/main/src/base/address.ts#L147)
**Source:** [src/base/address.ts:192](https://github.com/stellar/js-stellar-sdk/blob/main/src/base/address.ts#L192)

## Contract

Expand Down
54 changes: 54 additions & 0 deletions scripts/post-process-generated.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#!/usr/bin/env python3
"""Post-process xdrgen JS output to inline xdr.const values at usage sites.

xdrgen master emits `xdr.const("NAME", N);` to register a constant in the
xdr namespace, then uses the bare identifier later (`xdr.string(NAME)`).
But `@stellar/js-xdr`'s TypeBuilder.const() does not put NAME into JS scope,
so the bare identifier ReferenceErrors at runtime.

Injecting `var NAME = N;` at the IIFE top fixes runtime but gets DCE'd by
terser in the production browser dist. The robust fix is to inline the
literal at each usage site so there's no identifier for terser to drop.

The `xdr.const("NAME", N);` declaration itself is left untouched: the NAME
there is a string literal (preceded by a quote), so the negative lookbehind
below skips it. Constants only referenced via `xdr.lookup("NAME")` string
lookups are likewise untouched.
"""
import re
import pathlib
import sys


def inline_consts(path: pathlib.Path) -> int:
s = path.read_text()
consts = dict(re.findall(
r'xdr\.const\("([A-Z][A-Z0-9_]+)",\s*(0x[0-9a-fA-F]+|\d+)\);', s
))
n_replaced = 0
for name, value in consts.items():
# Replace bare identifier (not preceded by quote or word char,
# not followed by quote or word char). This skips string literals
# like "NAME" and xdr.lookup("NAME"), so the xdr.const(...)
# declaration's string name is preserved.
new_s, count = re.subn(
rf'(?<![\w"\'$]){re.escape(name)}(?![\w"\'$])',
value,
s,
)
if count > 0:
s = new_s
n_replaced += count
path.write_text(s)
return n_replaced


if __name__ == "__main__":
files = sys.argv[1:] or [
"src/base/generated/curr_generated.js",
"src/base/generated/next_generated.js",
]
for f in files:
p = pathlib.Path(f)
n = inline_consts(p)
print(f"{f}: inlined {n} bare-identifier const reference(s)")
Loading
Loading