|
| 1 | +--- |
| 2 | +description: Generating and decoding addresses on the Stacks blockchain. |
| 3 | +--- |
| 4 | + |
| 5 | +# c32check |
| 6 | + |
| 7 | +{% hint style="info" %} |
| 8 | +For the c32check open-source repo: [https://github.com/stacks-network/c32check](https://github.com/stacks-network/c32check) |
| 9 | +{% endhint %} |
| 10 | + |
| 11 | +The Stacks blockchain uses c32-encoded public key hashes as addresses. Specifically, a **c32check address** is a c32check-encoded ripemd160 hash. This library is meant for generating and decoding addresses on the Stacks blockchain. |
| 12 | + |
| 13 | +### How it works |
| 14 | + |
| 15 | +Each c32check string encodes a 1-byte version and a 4-byte checksum. When decoded as a hex string, the wire format looks like this: |
| 16 | + |
| 17 | +``` |
| 18 | +0 1 n+1 n+5 |
| 19 | +|------|-----------------------------|---------------| |
| 20 | +version n-byte hex payload 4-byte hash |
| 21 | +``` |
| 22 | + |
| 23 | +If `version` is the version byte (a 1-byte `number`) and `payload` is the raw bytes (e.g. as a `string`), then the `checksum` is calculated as follows: |
| 24 | + |
| 25 | +``` |
| 26 | +checksum = sha256(sha256(version + payload)).substring(0,4) |
| 27 | +``` |
| 28 | + |
| 29 | +In other words, the checksum is the first four bytes of the double-sha256 of the bytestring concatenation of the `version` and `payload`. This is similar to base58check encoding, for example. |
| 30 | + |
| 31 | +### Examples |
| 32 | + |
| 33 | +**Installation** |
| 34 | + |
| 35 | +{% code title="terminal" %} |
| 36 | +```shellscript |
| 37 | +npm install c32check |
| 38 | +``` |
| 39 | +{% endcode %} |
| 40 | + |
| 41 | +```typescript |
| 42 | +> c32 = require('c32check') |
| 43 | +{ c32encode: [Function: c32encode], |
| 44 | + c32decode: [Function: c32decode], |
| 45 | + c32checkEncode: [Function: c32checkEncode], |
| 46 | + c32checkDecode: [Function: c32checkDecode], |
| 47 | + c32address: [Function: c32address], |
| 48 | + c32addressDecode: [Function: c32addressDecode], |
| 49 | + versions: |
| 50 | + { mainnet: { p2pkh: 22, p2sh: 20 }, |
| 51 | + testnet: { p2pkh: 26, p2sh: 21 } }, |
| 52 | + c32ToB58: [Function: c32ToB58], |
| 53 | + b58ToC32: [Function: b58ToC32] } |
| 54 | +``` |
| 55 | + |
| 56 | +#### c32encode, c32decode |
| 57 | + |
| 58 | +```typescript |
| 59 | +> c32check.c32encode(Buffer.from('hello world').toString('hex')) |
| 60 | +'38CNP6RVS0EXQQ4V34' |
| 61 | +> c32check.c32decode('38CNP6RVS0EXQQ4V34') |
| 62 | +'68656c6c6f20776f726c64' |
| 63 | +> Buffer.from('68656c6c6f20776f726c64', 'hex').toString() |
| 64 | +'hello world' |
| 65 | +``` |
| 66 | + |
| 67 | +#### c32checkEncode, c32checkDecode |
| 68 | + |
| 69 | +```typescript |
| 70 | +> version = 12 |
| 71 | +> c32check.c32checkEncode(version, Buffer.from('hello world').toString('hex')) |
| 72 | +'CD1JPRV3F41VPYWKCCGRMASC8' |
| 73 | +> c32check.c32checkDecode('CD1JPRV3F41VPYWKCCGRMASC8') |
| 74 | +[ 12, '68656c6c6f20776f726c64' ] |
| 75 | +> Buffer.from('68656c6c6f20776f726c64', 'hex').toString() |
| 76 | +'hello world' |
| 77 | +``` |
| 78 | + |
| 79 | +#### c32address, c32addressDecode |
| 80 | + |
| 81 | +> **Note**: These methods only work on ripemd160 hashes |
| 82 | +
|
| 83 | +```typescript |
| 84 | +> hash160 = 'a46ff88886c2ef9762d970b4d2c63678835bd39d' |
| 85 | +> version = c32check.versions.mainnet.p2pkh |
| 86 | +22 |
| 87 | +> c32check.c32address(version, hash160) |
| 88 | +'SP2J6ZY48GV1EZ5V2V5RB9MP66SW86PYKKNRV9EJ7' |
| 89 | +> c32check.c32addressDecode('SP2J6ZY48GV1EZ5V2V5RB9MP66SW86PYKKNRV9EJ7') |
| 90 | +[ 22, 'a46ff88886c2ef9762d970b4d2c63678835bd39d' ] |
| 91 | +``` |
| 92 | + |
| 93 | +#### c32ToB58, b58ToC32 |
| 94 | + |
| 95 | +Convert a Stacks address to its corresponding Bitcoin address, or vice versa. |
| 96 | + |
| 97 | +> **Note**: Common address versions are converted between c32check and base58check seamlessly, in order to accommodate Stacks addresses. |
| 98 | +
|
| 99 | +```typescript |
| 100 | +> b58addr = '16EMaNw3pkn3v6f2BgnSSs53zAKH4Q8YJg' |
| 101 | +> c32check.b58ToC32(b58addr) |
| 102 | +'SPWNYDJ3STG7XH7ERWXMV6MQ7Q6EATWVY5Q1QMP8' |
| 103 | +> c32check.c32ToB58('SPWNYDJ3STG7XH7ERWXMV6MQ7Q6EATWVY5Q1QMP8') |
| 104 | +'16EMaNw3pkn3v6f2BgnSSs53zAKH4Q8YJg' |
| 105 | +``` |
| 106 | + |
| 107 | +```typescript |
| 108 | +> b58addr = '3D2oetdNuZUqQHPJmcMDDHYoqkyNVsFk9r' |
| 109 | +> c32check.b58ToC32(b58addr) |
| 110 | +'SM1Y6EXF21RZ9739DFTEQKB1H044BMM0XVCM4A4NY' |
| 111 | +> c32check.c32ToB58('SM1Y6EXF21RZ9739DFTEQKB1H044BMM0XVCM4A4NY') |
| 112 | +'3D2oetdNuZUqQHPJmcMDDHYoqkyNVsFk9r' |
| 113 | +``` |
0 commit comments