Skip to content

Commit 9ffd035

Browse files
committed
add pubkey decoder logic to accountFromAny
1 parent 3ae82ef commit 9ffd035

File tree

3 files changed

+62
-11
lines changed

3 files changed

+62
-11
lines changed

networks/cosmos/src/utils/index.ts

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ export interface Account {
3232
readonly sequence: number;
3333
}
3434

35+
export interface AccountFromAnyOption {
36+
readonly pubkeyDecoders?: Record<string, (pubkey: Any) => Pubkey>;
37+
}
38+
3539
/**
3640
* Extracts a BaseAccount from simple wrapper account types using binary parsing.
3741
* This handles simple wrapper account types like ModuleAccount that contain
@@ -86,13 +90,14 @@ function extractBaseAccountFromWrapper(value: Uint8Array): BaseAccount | null {
8690
* @returns A standardized Account object
8791
* @throws Error if the account type is not supported
8892
*/
89-
export function accountFromAny(accountAny: Any): Account {
93+
export function accountFromAny(accountAny: Any, opts?: AccountFromAnyOption): Account {
94+
const pubkeyDecoders = opts?.pubkeyDecoders;
9095
switch (accountAny.typeUrl) {
9196
case "/cosmos.auth.v1beta1.BaseAccount": {
9297
const baseAccount = BaseAccount.decode(accountAny.value);
9398
return {
9499
address: baseAccount.address,
95-
pubkey: decodeOptionalPubkey(baseAccount.pubKey),
100+
pubkey: decodeOptionalPubkey(baseAccount.pubKey, pubkeyDecoders),
96101
accountNumber: Number(baseAccount.accountNumber),
97102
sequence: Number(baseAccount.sequence),
98103
};
@@ -107,7 +112,7 @@ export function accountFromAny(accountAny: Any): Account {
107112

108113
return {
109114
address: baseAccount.address,
110-
pubkey: decodeOptionalPubkey(baseAccount.pubKey),
115+
pubkey: decodeOptionalPubkey(baseAccount.pubKey, pubkeyDecoders),
111116
accountNumber: Number(baseAccount.accountNumber),
112117
sequence: Number(baseAccount.sequence),
113118
};
@@ -122,7 +127,7 @@ export function accountFromAny(accountAny: Any): Account {
122127

123128
return {
124129
address: baseAccount.address,
125-
pubkey: decodeOptionalPubkey(baseAccount.pubKey),
130+
pubkey: decodeOptionalPubkey(baseAccount.pubKey, pubkeyDecoders),
126131
accountNumber: Number(baseAccount.accountNumber),
127132
sequence: Number(baseAccount.sequence),
128133
};
@@ -137,7 +142,7 @@ export function accountFromAny(accountAny: Any): Account {
137142

138143
return {
139144
address: baseAccount.address,
140-
pubkey: decodeOptionalPubkey(baseAccount.pubKey),
145+
pubkey: decodeOptionalPubkey(baseAccount.pubKey, pubkeyDecoders),
141146
accountNumber: Number(baseAccount.accountNumber),
142147
sequence: Number(baseAccount.sequence),
143148
};
@@ -152,7 +157,7 @@ export function accountFromAny(accountAny: Any): Account {
152157

153158
return {
154159
address: baseAccount.address,
155-
pubkey: decodeOptionalPubkey(baseAccount.pubKey),
160+
pubkey: decodeOptionalPubkey(baseAccount.pubKey, pubkeyDecoders),
156161
accountNumber: Number(baseAccount.accountNumber),
157162
sequence: Number(baseAccount.sequence),
158163
};
@@ -164,7 +169,7 @@ export function accountFromAny(accountAny: Any): Account {
164169
if (baseAccount) {
165170
return {
166171
address: baseAccount.address,
167-
pubkey: decodeOptionalPubkey(baseAccount.pubKey),
172+
pubkey: decodeOptionalPubkey(baseAccount.pubKey, pubkeyDecoders),
168173
accountNumber: Number(baseAccount.accountNumber),
169174
sequence: Number(baseAccount.sequence),
170175
};
@@ -235,4 +240,3 @@ export { generateMnemonic };
235240

236241
// Re-export fee helpers
237242
export * from './fee';
238-

networks/cosmos/src/utils/utils.test.ts

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,43 @@ describe("accountFromAny", () => {
7171
sequence: 7,
7272
});
7373
});
74+
75+
it("should use custom pubkey decoder when decodePubkey fails", () => {
76+
const customTypeUrl = "/custom.crypto.v1.CustomPubKey";
77+
const fallbackPubkey = testPubkey;
78+
79+
const baseAccount: BaseAccount = {
80+
address: testAddress,
81+
pubKey: {
82+
typeUrl: customTypeUrl,
83+
value: Uint8Array.from([1, 2, 3]),
84+
},
85+
accountNumber: testAccountNumber,
86+
sequence: testSequence,
87+
};
88+
89+
const accountAny: Any = {
90+
typeUrl: "/cosmos.auth.v1beta1.BaseAccount",
91+
value: BaseAccount.encode(baseAccount).finish(),
92+
};
93+
94+
const decoder = jest.fn().mockReturnValue(fallbackPubkey);
95+
96+
const result = accountFromAny(accountAny, {
97+
pubkeyDecoders: {
98+
[customTypeUrl]: decoder,
99+
},
100+
});
101+
102+
expect(decoder).toHaveBeenCalledTimes(1);
103+
expect(decoder).toHaveBeenCalledWith(expect.objectContaining({ typeUrl: customTypeUrl }));
104+
expect(result).toEqual({
105+
address: testAddress,
106+
pubkey: fallbackPubkey,
107+
accountNumber: 42,
108+
sequence: 7,
109+
});
110+
});
74111
});
75112

76113
describe("Wrapper account types using binary parsing", () => {
@@ -295,4 +332,3 @@ describe("accountFromAny", () => {
295332
});
296333
});
297334
});
298-

packages/pubkey/src/pubkey.ts

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,12 +108,23 @@ export function decodePubkey(pubkey: Any): Pubkey {
108108
* This supports single pubkeys such as Cosmos ed25519 and secp256k1 keys
109109
* as well as multisig threshold pubkeys.
110110
*/
111-
export function decodeOptionalPubkey(pubkey: Any | null | undefined): Pubkey | null {
111+
export function decodeOptionalPubkey(
112+
pubkey: Any | null | undefined,
113+
pubkeyDecoders?: Record<string, (pubkey: Any) => Pubkey>
114+
): Pubkey | null {
112115
if (!pubkey) return null;
113116
if (pubkey.typeUrl) {
114117
if (pubkey.value.length) {
115118
// both set
116-
return decodePubkey(pubkey);
119+
try {
120+
return decodePubkey(pubkey);
121+
} catch (error) {
122+
const decoder = pubkeyDecoders?.[pubkey.typeUrl];
123+
if (decoder) {
124+
return decoder(pubkey);
125+
}
126+
throw error;
127+
}
117128
} else {
118129
throw new Error(`Pubkey is an Any with type URL '${pubkey.typeUrl}' but an empty value`);
119130
}

0 commit comments

Comments
 (0)