@@ -221,7 +221,7 @@ const isMap = (arg: unknown) => {
221221 Array . isArray ( arg ) &&
222222 arg . every ( ( obj : AnyObject ) => {
223223 // Check if object has exactly two keys: "0" and "1"
224- const keys = Object . keys ( obj as object ) ;
224+ const keys = Object . keys ( obj ) ;
225225 if ( keys . length !== 2 || ! keys . includes ( "0" ) || ! keys . includes ( "1" ) ) {
226226 return false ;
227227 }
@@ -276,7 +276,6 @@ const getScValFromArg = (arg: unknown, scVals: xdr.ScVal[]): xdr.ScVal => {
276276
277277 return xdr . ScVal . scvVec ( arrayScVals ) ;
278278 }
279-
280279 return getScValsFromArgs ( { arg : arg as AnyObject } , scVals || [ ] ) [ 0 ] ;
281280} ;
282281
@@ -293,19 +292,27 @@ const convertEnumToScVal = (
293292 obj : Record < string , unknown > ,
294293 scVals ?: xdr . ScVal [ ] ,
295294) => {
296- // TUPLE CASE
295+ // Tuple Case
297296 if ( obj . tag && obj . values ) {
298297 const tagVal = nativeToScVal ( obj . tag , { type : "symbol" } ) ;
299298 const valuesVal = convertValuesToScVals (
300299 obj . values as unknown [ ] ,
301300 scVals || [ ] ,
302301 ) ;
303302 const tupleScValsVec = xdr . ScVal . scvVec ( [ tagVal , ...valuesVal ] ) ;
304-
305303 return tupleScValsVec ;
306304 }
307305
308- // ENUM CASE
306+ // Enum Integer Variant Case
307+ if ( obj . enum ) {
308+ return nativeToScVal ( obj . enum , { type : "u32" } ) ;
309+ }
310+
311+ if ( ! obj . tag ) {
312+ // If no tag is present, we assume it's a primitive value
313+ return getScValFromArg ( obj , scVals || [ ] ) ;
314+ }
315+ // Enum Case Unit Case
309316 const tagVec = [ obj . tag ] ;
310317 return nativeToScVal ( tagVec , { type : "symbol" } ) ;
311318} ;
@@ -407,12 +414,35 @@ const convertObjectToMap = (
407414
408415 return { mapVal, mapType } ;
409416} ;
410-
411417type TupleValue = {
412418 value : unknown ;
413419 type : string ;
414420} ;
415421
422+ // Helper function to detect if string is base64 or hex
423+ const detectBytesEncoding = ( value : string ) : "base64" | "hex" => {
424+ const hexRegex = / ^ [ 0 - 9 a - f A - F ] + $ / ;
425+ const base64Regex = / ^ [ A - Z a - z 0 - 9 + / ] * = { 0 , 2 } $ / ;
426+
427+ if ( hexRegex . test ( value ) && value . length % 2 === 0 ) {
428+ return "hex" ;
429+ }
430+
431+ if ( base64Regex . test ( value ) && value . length % 4 === 0 ) {
432+ try {
433+ const decoded = Buffer . from ( value , "base64" ) ;
434+ return decoded . toString ( "base64" ) . replace ( / = + $ / , "" ) ===
435+ value . replace ( / = + $ / , "" )
436+ ? "base64"
437+ : "hex" ;
438+ } catch {
439+ return "hex" ;
440+ }
441+ }
442+
443+ return "base64" ;
444+ } ;
445+
416446const convertTupleToScVal = ( tupleArray : TupleValue [ ] ) => {
417447 const tupleScVals = tupleArray . map ( ( v ) => {
418448 if ( v . type === "bool" ) {
@@ -431,45 +461,46 @@ const convertTupleToScVal = (tupleArray: TupleValue[]) => {
431461} ;
432462
433463type PrimitiveArg = { type : string ; value : unknown } ;
434- type EnumArg = { tag : string ; values ?: unknown [ ] } ;
435464
436465const getScValFromPrimitive = ( v : PrimitiveArg ) => {
437466 if ( v . type === "bool" ) {
438- const boolValue = v . value === "true" ;
467+ const boolValue = v . value === "true" ? true : false ;
439468 return nativeToScVal ( boolValue ) ;
440469 }
441470 if ( v . type === "bytes" && typeof v . value === "string" ) {
442- return nativeToScVal ( new Uint8Array ( Buffer . from ( v . value , "base64" ) ) ) ;
471+ const encoding = detectBytesEncoding ( v . value ) ;
472+ return nativeToScVal ( new Uint8Array ( Buffer . from ( v . value , encoding ) ) ) ;
443473 }
444474 return nativeToScVal ( v . value , { type : v . type } ) ;
445475} ;
446476
447- const getScValsFromArgs = (
477+ export const getScValsFromArgs = (
448478 args : SorobanInvokeValue [ "args" ] ,
449479 scVals : xdr . ScVal [ ] = [ ] ,
450480) : xdr . ScVal [ ] => {
451- // PRIMITIVE CASE
481+ // Primitive Case
452482 if (
453483 Object . values ( args ) . every (
454- ( v ) : v is PrimitiveArg =>
455- typeof v === "object" && v !== null && "type" in v && "value" in v ,
484+ ( v : unknown ) => ( v as AnyObject ) . type && ( v as AnyObject ) . value ,
456485 )
457486 ) {
458- const primitiveScVals = Object . values ( args ) . map ( ( v ) =>
459- getScValFromPrimitive ( v as PrimitiveArg ) ,
460- ) ;
487+ const primitiveScVals = Object . values ( args ) . map ( ( v ) => {
488+ return getScValFromPrimitive ( v as PrimitiveArg ) ;
489+ } ) ;
490+
461491 return primitiveScVals ;
462492 }
463493
464- // ENUM (VOID AND COMPLEX ONE LIKE TUPLE) CASE
494+ // Enum (Void and Complex One Like Tuple) Case
465495 if (
466496 Object . values ( args ) . some (
467- ( v ) : v is EnumArg => typeof v === "object" && v !== null && "tag" in v ,
497+ ( v : unknown ) => ( v as AnyObject ) . tag || ( v as AnyObject ) . enum ,
468498 )
469499 ) {
470- const enumScVals = Object . values ( args ) . map ( ( v ) =>
471- convertEnumToScVal ( v as EnumArg , scVals ) ,
472- ) ;
500+ const enumScVals = Object . values ( args ) . map ( ( v ) => {
501+ return convertEnumToScVal ( v as AnyObject , scVals ) ;
502+ } ) ;
503+
473504 return enumScVals ;
474505 }
475506
@@ -478,15 +509,15 @@ const getScValsFromArgs = (
478509
479510 // Check if it's an array of map objects
480511 if ( Array . isArray ( argValue ) ) {
481- // MAP CASE
512+ // Map Case
482513 if ( isMap ( argValue ) ) {
483514 const { mapVal, mapType } = convertObjectToMap ( argValue ) ;
484515 const mapScVal = nativeToScVal ( mapVal , { type : mapType } ) ;
485516 scVals . push ( mapScVal ) ;
486517 return scVals ;
487518 }
488519
489- // VEC CASE #1: array of objects or complicated tuple case
520+ // Vec Case #1: array of objects or complicated tuple case
490521 if ( argValue . some ( ( v ) => typeof Object . values ( v ) [ 0 ] === "object" ) ) {
491522 const arrayScVals = argValue . map ( ( v ) => {
492523 if ( v . tag ) {
@@ -501,7 +532,7 @@ const getScValsFromArgs = (
501532 return scVals ;
502533 }
503534
504- // VEC CASE #2: array of primitives
535+ // Vec Case #2: array of primitives
505536 const isVecArray = argValue . every ( ( v ) => {
506537 return v . type === argValue [ 0 ] . type ;
507538 } ) ;
@@ -511,7 +542,8 @@ const getScValsFromArgs = (
511542 if ( v . type === "bool" ) {
512543 acc . push ( v . value === "true" ? true : false ) ;
513544 } else if ( v . type === "bytes" ) {
514- acc . push ( new Uint8Array ( Buffer . from ( v . value , "base64" ) ) ) ;
545+ const encoding = detectBytesEncoding ( v . value ) ;
546+ acc . push ( new Uint8Array ( Buffer . from ( v . value , encoding ) ) ) ;
515547 } else {
516548 acc . push ( v . value ) ;
517549 }
@@ -526,8 +558,8 @@ const getScValsFromArgs = (
526558 return scVals ;
527559 }
528560
529- // TUPLE CASE
530- const isTupleArray = argValue . every ( ( v : AnyObject ) => v . type && v . value ) ;
561+ // Tuple Case
562+ const isTupleArray = argValue . every ( ( v ) => v . type && v . value ) ;
531563 if ( isTupleArray ) {
532564 const tupleScValsVec = convertTupleToScVal ( argValue ) ;
533565
@@ -536,25 +568,18 @@ const getScValsFromArgs = (
536568 }
537569 }
538570
539- // OBJECT CASE
571+ // Object Case
540572 if (
541- Object . values ( argValue as object ) . every (
542- ( v : AnyObject ) => v . type && v . value ,
573+ Object . values ( argValue as AnyObject ) . every (
574+ ( v ) => ( v as AnyObject ) . type && ( v as AnyObject ) . value ,
543575 )
544576 ) {
545577 const convertedObj = convertObjectToScVal ( argValue as AnyObject ) ;
546578 scVals . push ( nativeToScVal ( convertedObj ) ) ;
547579 return scVals ;
548580 }
549581
550- if (
551- typeof argValue === "object" &&
552- argValue &&
553- "type" in argValue &&
554- "value" in argValue &&
555- argValue . type &&
556- argValue . value
557- ) {
582+ if ( ( argValue as AnyObject ) . type && ( argValue as AnyObject ) . value ) {
558583 scVals . push ( getScValFromPrimitive ( argValue as PrimitiveArg ) ) ;
559584 }
560585 }
0 commit comments