Skip to content
Open
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
7 changes: 5 additions & 2 deletions src/strkey.js
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@ function isValid(versionByteName, encoded) {
break;

case 'claimableBalance':
if (encoded.length !== 58) {
if (encoded.length !== 56 && encoded.length !== 58) {
return false;
}
Comment on lines +305 to 307
break;
Expand Down Expand Up @@ -341,7 +341,10 @@ function isValid(versionByteName, encoded) {
return decoded.length === 32;

case 'claimableBalance':
return decoded.length === 32 + 1; // +1 byte for discriminant
return (
decoded.length === 32 ||

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Preserve the v0 discriminant for Address conversion

When a standard 56-character claimable-balance StrKey is now accepted here, new Address(bAddress) stores only the 32-byte hash returned by decodeClaimableBalance; later Address.toScAddress() treats this._key.at(0) as the claimable-balance discriminant and subarray(1) as the payload. For any code that parses one of these newly-valid B-addresses and converts it to an ScAddress, the first hash byte is used as the enum value instead of v0, so conversion throws or builds the wrong XDR. The newly accepted 32-byte form needs to be normalized to the existing v0+hash representation before Address uses it.

Useful? React with 👍 / 👎.

(decoded.length === 32 + 1 && decoded[0] === 0)
);
Comment on lines +344 to +347

case 'med25519PublicKey':
return decoded.length === 40; // +8 bytes for the ID
Expand Down
23 changes: 23 additions & 0 deletions test/unit/strkey_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -429,6 +429,20 @@ describe('StrKey', function () {
});

describe('#claimableBalances', function () {
it('valid w/ 32-byte strkey', function () {
const strkey =
'BA7QYNF7SOWQ3GLR2BGMZEHXAVIRZA4KVWLTJJFC7MGXUA74P7UJV5AS';
const asHex =
'3f0c34bf93ad0d9971d04ccc90f705511c838aad9734a4a2fb0d7a03fc7fe89a';
expect(StellarBase.StrKey.isValidClaimableBalance(strkey)).to.be.true;
expect(
StellarBase.StrKey.decodeClaimableBalance(strkey).toString('hex')
).to.equal(asHex);
expect(
StellarBase.StrKey.encodeClaimableBalance(Buffer.from(asHex, 'hex'))
).to.equal(strkey);
});

it('valid w/ 33-byte strkey', function () {
const strkey =
'BAAD6DBUX6J22DMZOHIEZTEQ64CVCHEDRKWZONFEUL5Q26QD7R76RGR4TU';
Expand All @@ -442,6 +456,15 @@ describe('StrKey', function () {
StellarBase.StrKey.encodeClaimableBalance(Buffer.from(asHex, 'hex'))
).to.equal(strkey);
});

it('rejects a 33-byte strkey with a non-v0 discriminant', function () {
const asHex =
'013f0c34bf93ad0d9971d04ccc90f705511c838aad9734a4a2fb0d7a03fc7fe89a';
const strkey = StellarBase.StrKey.encodeClaimableBalance(
Buffer.from(asHex, 'hex')
);
Comment on lines +460 to +465
expect(StellarBase.StrKey.isValidClaimableBalance(strkey)).to.be.false;
});
});

describe('#invalidStrKeys', function () {
Expand Down