11import { fromBech32 , normalizeBech32 , toBech32 } from '@cosmjs/encoding' ;
22import { PublicKey } from '@solana/web3.js' ;
33import { Wallet , utils as ethersUtils } from 'ethers' ;
4+ import {
5+ addAddressPadding ,
6+ encode ,
7+ num ,
8+ validateAndParseAddress ,
9+ } from 'starknet' ;
410
511import { isNullish } from './typeof.js' ;
612import { Address , HexString , ProtocolType } from './types.js' ;
713import { assert } from './validation.js' ;
814
915const EVM_ADDRESS_REGEX = / ^ 0 x [ a - f A - F 0 - 9 ] { 40 } $ / ;
1016const SEALEVEL_ADDRESS_REGEX = / ^ [ a - z A - Z 0 - 9 ] { 36 , 44 } $ / ;
17+ const STARKNET_ADDRESS_REGEX = / ^ ( 0 x ) ? [ 0 - 9 a - f A - F ] { 64 } $ / ;
1118
1219const HEX_BYTES32_REGEX = / ^ 0 x [ a - f A - F 0 - 9 ] { 64 } $ / ;
1320
@@ -24,10 +31,12 @@ const COSMOS_FACTORY_TOKEN_REGEX = new RegExp(
2431const EVM_TX_HASH_REGEX = / ^ 0 x ( [ A - F a - f 0 - 9 ] { 64 } ) $ / ;
2532const SEALEVEL_TX_HASH_REGEX = / ^ [ a - z A - Z 1 - 9 ] { 88 } $ / ;
2633const COSMOS_TX_HASH_REGEX = / ^ ( 0 x ) ? [ A - F a - f 0 - 9 ] { 64 } $ / ;
34+ const STARKNET_TX_HASH_REGEX = / ^ ( 0 x ) ? [ 0 - 9 a - f A - F ] { 64 } $ / ;
2735
2836const EVM_ZEROISH_ADDRESS_REGEX = / ^ ( 0 x ) ? 0 * $ / ;
2937const SEALEVEL_ZEROISH_ADDRESS_REGEX = / ^ 1 + $ / ;
3038const COSMOS_ZEROISH_ADDRESS_REGEX = / ^ [ a - z ] { 1 , 10 } ?1 [ 0 ] + $ / ;
39+ const STARKNET_ZEROISH_ADDRESS_REGEX = / ^ ( 0 x ) ? 0 * $ / ;
3140
3241export const ZERO_ADDRESS_HEX_32 =
3342 '0x0000000000000000000000000000000000000000000000000000000000000000' ;
@@ -48,6 +57,10 @@ export function isAddressCosmos(address: Address) {
4857 ) ;
4958}
5059
60+ export function isAddressStarknet ( address : Address ) {
61+ return STARKNET_ADDRESS_REGEX . test ( address ) ;
62+ }
63+
5164export function getAddressProtocolType ( address : Address ) {
5265 if ( ! address ) return undefined ;
5366 if ( isAddressEvm ( address ) ) {
@@ -56,6 +69,8 @@ export function getAddressProtocolType(address: Address) {
5669 return ProtocolType . Cosmos ;
5770 } else if ( isAddressSealevel ( address ) ) {
5871 return ProtocolType . Sealevel ;
72+ } else if ( isAddressStarknet ( address ) ) {
73+ return ProtocolType . Starknet ;
5974 } else {
6075 return undefined ;
6176 }
@@ -112,13 +127,23 @@ export function isValidAddressCosmos(address: Address) {
112127 }
113128}
114129
130+ export function isValidAddressStarknet ( address : Address ) {
131+ try {
132+ const isValid = address && validateAndParseAddress ( address ) ;
133+ return ! ! isValid ;
134+ } catch {
135+ return false ;
136+ }
137+ }
138+
115139export function isValidAddress ( address : Address , protocol ?: ProtocolType ) {
116140 return routeAddressUtil (
117141 {
118142 [ ProtocolType . Ethereum ] : isValidAddressEvm ,
119143 [ ProtocolType . Sealevel ] : isValidAddressSealevel ,
120144 [ ProtocolType . Cosmos ] : isValidAddressCosmos ,
121145 [ ProtocolType . CosmosNative ] : isValidAddressCosmos ,
146+ [ ProtocolType . Starknet ] : isValidAddressStarknet ,
122147 } ,
123148 address ,
124149 false ,
@@ -153,6 +178,14 @@ export function normalizeAddressCosmos(address: Address) {
153178 }
154179}
155180
181+ export function normalizeAddressStarknet ( address : Address ) {
182+ if ( isZeroishAddress ( address ) ) return address ;
183+ try {
184+ return validateAndParseAddress ( address ) ;
185+ } catch {
186+ return address ;
187+ }
188+ }
156189export function normalizeAddress ( address : Address , protocol ?: ProtocolType ) {
157190 return routeAddressUtil (
158191 {
@@ -179,6 +212,10 @@ export function eqAddressCosmos(a1: Address, a2: Address) {
179212 return normalizeAddressCosmos ( a1 ) === normalizeAddressCosmos ( a2 ) ;
180213}
181214
215+ export function eqAddressStarknet ( a1 : Address , a2 : Address ) {
216+ return normalizeAddressStarknet ( a1 ) === normalizeAddressStarknet ( a2 ) ;
217+ }
218+
182219export function eqAddress ( a1 : Address , a2 : Address ) {
183220 const p1 = getAddressProtocolType ( a1 ) ;
184221 const p2 = getAddressProtocolType ( a2 ) ;
@@ -189,6 +226,7 @@ export function eqAddress(a1: Address, a2: Address) {
189226 [ ProtocolType . Sealevel ] : ( _a1 ) => eqAddressSol ( _a1 , a2 ) ,
190227 [ ProtocolType . Cosmos ] : ( _a1 ) => eqAddressCosmos ( _a1 , a2 ) ,
191228 [ ProtocolType . CosmosNative ] : ( _a1 ) => eqAddressCosmos ( _a1 , a2 ) ,
229+ [ ProtocolType . Starknet ] : ( _a1 ) => eqAddressStarknet ( _a1 , a2 ) ,
192230 } ,
193231 a1 ,
194232 false ,
@@ -208,6 +246,10 @@ export function isValidTransactionHashCosmos(input: string) {
208246 return COSMOS_TX_HASH_REGEX . test ( input ) ;
209247}
210248
249+ export function isValidTransactionHashStarknet ( input : string ) {
250+ return STARKNET_TX_HASH_REGEX . test ( input ) ;
251+ }
252+
211253export function isValidTransactionHash ( input : string , protocol : ProtocolType ) {
212254 if ( protocol === ProtocolType . Ethereum ) {
213255 return isValidTransactionHashEvm ( input ) ;
@@ -217,6 +259,8 @@ export function isValidTransactionHash(input: string, protocol: ProtocolType) {
217259 return isValidTransactionHashCosmos ( input ) ;
218260 } else if ( protocol === ProtocolType . CosmosNative ) {
219261 return isValidTransactionHashCosmos ( input ) ;
262+ } else if ( protocol === ProtocolType . Starknet ) {
263+ return isValidTransactionHashStarknet ( input ) ;
220264 } else {
221265 return false ;
222266 }
@@ -226,7 +270,8 @@ export function isZeroishAddress(address: Address) {
226270 return (
227271 EVM_ZEROISH_ADDRESS_REGEX . test ( address ) ||
228272 SEALEVEL_ZEROISH_ADDRESS_REGEX . test ( address ) ||
229- COSMOS_ZEROISH_ADDRESS_REGEX . test ( address )
273+ COSMOS_ZEROISH_ADDRESS_REGEX . test ( address ) ||
274+ STARKNET_ZEROISH_ADDRESS_REGEX . test ( address )
230275 ) ;
231276}
232277
@@ -271,6 +316,11 @@ export function addressToBytesCosmos(address: Address): Uint8Array {
271316 return fromBech32 ( address ) . data ;
272317}
273318
319+ export function addressToBytesStarknet ( address : Address ) : Uint8Array {
320+ const normalizedAddress = validateAndParseAddress ( address ) ;
321+ return num . hexToBytes ( normalizedAddress ) ;
322+ }
323+
274324export function addressToBytes (
275325 address : Address ,
276326 protocol ?: ProtocolType ,
@@ -281,6 +331,7 @@ export function addressToBytes(
281331 [ ProtocolType . Sealevel ] : addressToBytesSol ,
282332 [ ProtocolType . Cosmos ] : addressToBytesCosmos ,
283333 [ ProtocolType . CosmosNative ] : addressToBytesCosmos ,
334+ [ ProtocolType . Starknet ] : addressToBytesStarknet ,
284335 } ,
285336 address ,
286337 new Uint8Array ( ) ,
@@ -349,6 +400,11 @@ export function bytesToAddressCosmos(
349400 return toBech32 ( prefix , bytes ) ;
350401}
351402
403+ export function bytesToAddressStarknet ( bytes : Uint8Array ) : Address {
404+ const hexString = encode . buf2hex ( bytes ) ;
405+ return addAddressPadding ( hexString ) ;
406+ }
407+
352408export function bytesToProtocolAddress (
353409 bytes : Uint8Array ,
354410 toProtocol : ProtocolType ,
@@ -366,6 +422,8 @@ export function bytesToProtocolAddress(
366422 return bytesToAddressCosmos ( bytes , prefix ! ) ;
367423 } else if ( toProtocol === ProtocolType . CosmosNative ) {
368424 return bytesToAddressCosmos ( bytes , prefix ! ) ;
425+ } else if ( toProtocol === ProtocolType . Starknet ) {
426+ return bytesToAddressStarknet ( bytes ) ;
369427 } else {
370428 throw new Error ( `Unsupported protocol for address ${ toProtocol } ` ) ;
371429 }
0 commit comments