Skip to content Search Apps Documentation Source Content File Folder Download Copy Actions State String Boolean Number Struct Map Slice Pointer Function Closure Reference Nil Package Type Interface Unknown

Community realm. Read the code first. Community realm, deployed by its author. Read the code before you interact or send coins.

keys.gno

2.03 Kb · 82 lines
 1package hyperlane
 2
 3import (
 4	"encoding/hex"
 5	"errors"
 6	"strings"
 7)
 8
 9// The Bitcoin base58 alphabet, which Solana writes its 32-byte keys in.
10const b58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
11
12// ParseKey32 reads a 32-byte key the way a person types one: 64 hex digits (with or without 0x), or a Solana
13// address in base58.
14func ParseKey32(s string) ([32]byte, error) {
15	var out [32]byte
16	s = strings.TrimSpace(s)
17	if h := strings.TrimPrefix(s, "0x"); len(h) == 64 {
18		b, err := hex.DecodeString(h)
19		if err != nil {
20			return out, errors.New("hyperlane: not hex: " + s)
21		}
22		copy(out[:], b)
23		return out, nil
24	}
25	if len(s) == 0 || len(s) > 44 {
26		return out, errors.New("hyperlane: not a 32-byte key in hex or base58: " + s)
27	}
28	digits := make([]byte, 0, 32) // the number so far, base 256, least significant first
29	for i := 0; i < len(s); i++ {
30		c := strings.IndexByte(b58, s[i])
31		if c < 0 {
32			return out, errors.New("hyperlane: not base58: " + s)
33		}
34		carry := c
35		for j := range digits {
36			carry += int(digits[j]) * 58
37			digits[j] = byte(carry)
38			carry >>= 8
39		}
40		for carry > 0 {
41			digits = append(digits, byte(carry))
42			carry >>= 8
43		}
44	}
45	zeros := len(s) - len(strings.TrimLeft(s, "1")) // each leading '1' is a leading zero byte
46	if zeros+len(digits) != 32 {
47		return out, errors.New("hyperlane: base58 key is not 32 bytes: " + s)
48	}
49	for i, d := range digits {
50		out[31-i] = d
51	}
52	return out, nil
53}
54
55// Base58 writes bytes the way Solana writes a key.
56func Base58(b []byte) string {
57	zeros := 0
58	for zeros < len(b) && b[zeros] == 0 {
59		zeros++
60	}
61	digits := make([]byte, 0, len(b)*138/100+1) // base 58, least significant first
62	for _, x := range b[zeros:] {
63		carry := int(x)
64		for j := range digits {
65			carry += int(digits[j]) << 8
66			digits[j] = byte(carry % 58)
67			carry /= 58
68		}
69		for carry > 0 {
70			digits = append(digits, byte(carry%58))
71			carry /= 58
72		}
73	}
74	out := make([]byte, zeros+len(digits))
75	for i := 0; i < zeros; i++ {
76		out[i] = '1'
77	}
78	for i, d := range digits {
79		out[len(out)-1-i] = b58[d]
80	}
81	return string(out)
82}