IOST Blockchain API
아래 객체들은 컨트랙트 코드 안에서 바로 사용할 수 있습니다.
storage 객체
모든 변수는 런타임에 메모리에 저장됩니다. IOST는 스마트 컨트랙트에서 데이터를 영속화할 수 있도록 storage 객체를 제공합니다.
'global' 접두어가 없는 API는 호출 중인 컨트랙트 자신의 스토리지를 읽고 씁니다. 'global' 접두어가 붙은 API는 다른 컨트랙트의 스토리지를 읽는 데 사용합니다.
Storage API
put(key, value, payer=contractOwner)
key-value 쌍을 스토리지에 저장합니다.
| 파라미터 | 타입 | 비고 |
|---|---|---|
| key | string | 65536 바이트를 넘을 수 없음 |
| value | string | 65536 바이트를 넘을 수 없음 |
| payer | string(선택) | 누가 ram 비용을 지불할지를 결정합니다. 비워두면 컨트랙트 발행자가 ram 비용을 지불합니다. |
반환값: 없음
예시:
// k-v 쌍을 스토리지에 저장하고 ram 비용은 컨트랙트 owner가 지불
storage.put("test-key", "test-value");
// k-v 쌍을 스토리지에 저장하고 ram 비용은 트랜잭션 발행자가 지불
storage.put("test-key", "test-value", tx.publisher);
get(key)
key로 스토리지에서 값을 가져옵니다.
| 파라미터 | 타입 | 비고 |
|---|---|---|
| key | string |
반환값: 존재하면 string, 존재하지 않으면 null
예시:
let v = storage.get("test-key");
if (v !== null) {
...
}
has(key)
해당 key가 스토리지에 존재하는지 확인합니다.
| 파라미터 | 타입 | 비고 |
|---|---|---|
| key | string |
반환값: bool (true: 존재, false: 없음)
예시:
if (storage.has("test-key")) {
...
}
del(key)
key로 스토리지에서 key-value 쌍을 삭제합니다.
| 파라미터 | 타입 | 비고 |
|---|---|---|
| key | string |
반환값: 없음
예시:
storage.del("test-key")
mapPut(key, field, value, payer=contractOwner)
(key, field, value) 쌍을 저장합니다. key+field로 value를 찾습니다.
| 파라미터 | 타입 | 비고 |
|---|---|---|
| key | string | 65536 바이트를 넘을 수 없음 |
| field | string | 65536 바이트를 넘을 수 없음 |
| value | string | 65536 바이트를 넘을 수 없음 |
| payer | string(선택) | 누가 ram 비용을 지불할지를 결정합니다. 비워두면 컨트랙트 발행자가 ram 비용을 지불합니다. |
반환값: 없음
예시:
// key-field-value 쌍을 저장하고 ram 비용은 컨트랙트 owner가 지불
storage.mapPut("test-key", "test-field", "test-value");
// key-field-value 쌍을 저장하고 ram 비용은 트랜잭션 발행자가 지불
storage.mapPut("test-key", "test-field", "test-value", tx.publisher);
mapGet(key, field)
(key, field) 쌍을 조회합니다. key+field로 value를 찾습니다.
| 파라미터 | 타입 | 비고 |
|---|---|---|
| key | string | |
| field | string |
반환값: 존재하면 string, 존재하지 않으면 null
예시:
let v = storage.mapGet("test-key", "test-field");
if (v !== null) {
...
}
mapHas(key, field)
(key, field) 쌍의 존재 여부를 확인합니다.
| 파라미터 | 타입 | 비고 |
|---|---|---|
| key | string | |
| field | string |
반환값: bool (true: 존재, false: 없음)
예시:
if (storage.mapHas("test-key", "test-field")) {
...
}
mapKeys(key)
해당 key가 가진 field 목록을 가져옵니다.
주의:
1. 이 API는 최대 256개의 field만 저장합니다. 초과하는 field는 저장되지도 반환되지도 않습니다. 2. 맵의 모든 키를 얻을 필요가 있다면 직접 관리하고 이 API를 사용하지 않을 것을 권장합니다.
| 파라미터 | 타입 | 비고 |
|---|---|---|
| key | string |
반환값: array[string] (field 배열)
mapLen(key)
mapKeys()의 길이를 반환합니다.
mapKeys와 동일한 주의 사항이 적용됩니다.
| 파라미터 | 타입 | 비고 |
|---|---|---|
| key | string |
반환값: int (field 개수)
mapDel(key, field)
(key, field, value) 쌍을 삭제합니다. key+field로 value를 삭제합니다.
| 파라미터 | 타입 | 비고 |
|---|---|---|
| key | string | |
| field | string |
반환값: 없음
Global Storage API
다른 컨트랙트의 스토리지를 읽는 API들입니다.
globalHas(contract, key)
지정한 컨트랙트의 스토리지에 key가 존재하는지 확인합니다.
| 파라미터 | 타입 | 비고 |
|---|---|---|
| contract | string | 컨트랙트 ID |
| key | string |
반환값: bool (true: 존재, false: 없음)
예시:
if (storage.globalHas("Contractxxxxxx", "test-key")) {
...
}
globalGet(contract, key)
지정한 컨트랙트의 스토리지에서 key로 value를 가져옵니다.
| 파라미터 | 타입 | 비고 |
|---|---|---|
| contract | string | 컨트랙트 ID |
| key | string |
반환값: 존재하면 value string, 없으면 null
예시:
let v = storage.globalGet("Contractxxxxxx", "test-key");
if (v !== null) {
...
}
globalMapHas(contract, key, field)
지정한 컨트랙트의 스토리지에 (key, field) 쌍이 존재하는지 확인합니다.
| 파라미터 | 타입 | 비고 |
|---|---|---|
| contract | string | 컨트랙트 ID |
| key | string | |
| field | string |
반환값: bool (true: 존재, false: 없음)
예시:
// auth.iost 컨트랙트의 스토리지를 읽어 계정 존재 여부 확인
accountExists(account) {
return storage.globalMapHas("auth.iost", "auth", account);
}
globalMapGet(contract, key, field)
다른 컨트랙트의 스토리지에서 (key, field) 쌍의 값을 가져옵니다.
| 파라미터 | 타입 | 비고 |
|---|---|---|
| contract | string | 컨트랙트 ID |
| key | string | |
| field | string |
반환값: 존재하면 value string, 없으면 null
예시:
let v = storage.globalMapGet("Contractxxxxxx", "test-key", "test-field");
if (v !== null) {
...
}
globalMapLen(contract, key)
다른 컨트랙트의 스토리지에서 특정 key가 가진 field 개수를 셉니다.
mapKeys와 동일한 주의 사항이 적용됩니다.
| 파라미터 | 타입 | 비고 |
|---|---|---|
| contract | string | 컨트랙트 ID |
| key | string |
반환값: int (field 개수)
globalMapKeys(contract, key)
다른 컨트랙트의 스토리지에서 특정 key가 가진 field 목록을 가져옵니다.
mapKeys와 동일한 주의 사항이 적용됩니다.
| 파라미터 | 타입 | 비고 |
|---|---|---|
| contract | string | 컨트랙트 ID |
| key | string |
반환값: array[string] (field 배열)
blockchain 객체
blockchain 객체는 시스템 API를 호출하거나 다른 컨트랙트의 abi를 호출하는 데 사용됩니다.
transfer(from, to, amount, memo)
iost 토큰을 송금합니다.
| 파라미터 | 타입 | 비고 |
|---|---|---|
| from | string | 토큰을 보내는 계정 |
| to | string | 토큰을 받는 계정 |
| amount | string | 송금 수량 |
| memo | string | 부가 정보 |
반환값: 없음
예시:
// 트랜잭션 발행자의 1.23 iost를 testacc로 송금
blockchain.transfer(tx.publisher, "testacc", "1.23", "this is memo")
withdraw(to, amount, memo)
컨트랙트에서 iost 토큰을 출금합니다. 다음과 동일합니다:
blockchain.transfer(blockchain.contractName(), to, amount, memo)
| 파라미터 | 타입 | 비고 |
|---|---|---|
| to | string | 토큰을 받는 계정 |
| amount | string | 송금 수량 |
| memo | string | 부가 정보 |
반환값: 없음
예시:
// 컨트랙트에서 1.23 iost를 testacc로 전송
blockchain.withdraw(tx.publisher, "1.23", "this is memo")
deposit(from, amount, memo)
iost 토큰을 컨트랙트에 입금합니다. 다음과 동일합니다:
blockchain.transfer(from, blockchain.contractName(), amount, memo)
| 파라미터 | 타입 | 비고 |
|---|---|---|
| from | string | 송금 계정 |
| amount | string | 송금 수량 |
| memo | string | 부가 정보 |
반환값: 없음
예시:
// 트랜잭션 발행자에서 1.23 iost를 컨트랙트로 전송
blockchain.deposit(tx.publisher, "1.23", "this is memo")
contractName()
컨트랙트 ID를 반환합니다.
파라미터: 없음
반환값: 컨트랙트 ID 문자열
publisher()
트랜잭션 발행자를 반환합니다.
파라미터: 없음
반환값: tx publisher 문자열
contractOwner()
컨트랙트 owner를 반환합니다.
파라미터: 없음
반환값: 컨트랙트 발행자 문자열
call(contract, abi, args)
다른 컨트랙트의 abi를 args와 함께 호출합니다.
| 파라미터 | 타입 | 비고 |
|---|---|---|
| contract | string | 컨트랙트 ID |
| abi | string | |
| args | array/string | 인자 배열, 또는 그 JSON 문자열 |
반환값: 호출된 컨트랙트의 반환값을 담은 JSON 문자열을 원소로 가지는 배열.
예시:
// token.iost의 balanceOf를 호출하여 admin의 iost 잔액 조회
let ret = blockchain.call("token.iost", "balanceOf", ["iost", "admin"])
console.log(ret[0]) // 주의: ret[0]이 balanceOf의 반환값
// vote.iost의 getResult를 호출하여 투표 결과 조회
let ret = blockchain.call("vote.iost", "getResult", ["1"])
let voteRes = JSON.parse(ret[0]) // vote.iost의 getResult가 배열을 반환하므로 JSON 파싱이 필요
callWithAuth(contract, abi, args)
호출 측 컨트랙트의 권한을 가지고 다른 컨트랙트의 abi를 호출합니다.
| 파라미터 | 타입 | 비고 |
|---|---|---|
| contract | string | 컨트랙트 ID |
| abi | string | |
| args | array/string | 인자 배열, 또는 그 JSON 문자열 |
반환값: 호출된 컨트랙트의 반환값을 담은 JSON 문자열을 원소로 가지는 배열.
예시:
// testacc로 20 iost 송금
blockchain.callWithAuth("token.iost", "transfer", ["iost", blockchain.contractName(), "testacc", "20", ""]);
// call을 사용하면 컨트랙트의 토큰 송금에는 권한이 필요하므로 오류가 발생합니다.
blockchain.call("token.iost", "transfer", ["iost", blockchain.contractName(), "testacc", "20", ""]); // throw error
requireAuth(account, permission)
지정 계정의 지정 권한이 제공되었는지 확인합니다.
| 파라미터 | 타입 | 비고 |
|---|---|---|
| account | string | |
| permission | string |
반환값: bool (true: 권한이 제공됨, false: 아님)
예시:
// testacc의 active 권한이 제공되었는지 확인
// 즉, 트랜잭션에 testacc의 active 키 서명이 포함되어 있는지를 확인
const ret = blockchain.requireAuth('testacc', 'active');
if (ret !== true) {
throw new Error("require auth failed");
}
receipt(data)
영수증을 생성합니다.
| 파라미터 | 타입 | 비고 |
|---|---|---|
| data | string |
반환값: 없음
예시:
testReceipt() {
blockchain.receipt("some receipt content")
}
이 컨트랙트의 testReceipt를 호출하면 TxReceipt에 다음과 같은 항목이 기록됩니다.
"receipts": [
{
"funcName": "Contractxxxxx/testReceipt",
"content": "some receipt content"
}
]
event(data)
이벤트를 발행합니다.
| 파라미터 | 타입 | 비고 |
|---|---|---|
| data | string |
반환값: 없음
예시:
testEvent() {
blockchain.event("some event content")
}
이 컨트랙트의 testEvent를 호출한 뒤에는 subscribe를 통해 이벤트를 받을 수 있습니다.
curl -X POST http://127.0.0.1:30001/subscribe -d '{"topics":["CONTRACT_EVENT"], "filter":{"contract_id":"Contractxxxxx"}}'
{"result":{"event":{"topic":"CONTRACT_EVENT","data":"some event content","time":"1557150634515314000"}}}
blockchain.contextInfo()
{"abi_name":"hello","caller":{"name":"admin","is_account":true},"contract_name":"ContractATrHLF6LnpzjwQ1iU4VB38cSCURYzeCSyH8nSFSw8Tnc","publisher":"admin"}
tx 객체와 block 객체
tx 객체에는 현재 트랜잭션의 정보가 담겨 있습니다. 속성은 다음과 같습니다.
{
time: 1541541540000000000, // 나노초
hash: "4mBbjkCYJQZz7hGSdnRKCLgGEkuhen1FCb6YDD7oLmtP",
expiration: 1541541540010000000, // 나노초
gasLimit: 100000,
gasRatio: 100,
authList: {"Gcv8c2tH8qZrUYnKdEEdTtASsxivic2834MQW6mgxqto":2}, // pubkey
publisher: "user0"
}
예시:
console.log(tx.publisher)
block 객체에는 현재 블록의 정보가 담겨 있습니다. 속성은 다음과 같습니다.
{
number: 132,
parentHash: "4mBbjkCYJQZz7hGSdnRKCLgGEkuhen1FCb6YDD7oLmtP", // 부모 블록 해시
witness: "6sNQa7PV2SFzqCBtQUcQYJGGoU7XaB6R4xuCQVXNZe6b", // 블록 생성자 pubkey. Producer 키는 계정 키와 다릅니다.
time: 1541541540000000000 // 나노초
}
예시:
console.log(block.time)
IOSTCrypto 객체
IOSTCrypto는 해시 함수와 서명 검증 함수를 제공합니다.
sha3(data)
sha3-256 해시를 계산합니다.
| 파라미터 | 타입 | 비고 |
|---|---|---|
| data | string |
반환값: 해시 바이트 배열을 base58로 인코딩한 문자열. (base58_encode(sha3_256(data)))
예시:
IOSTCrypto.sha3("Fule will be expensive. Everyone will have a small car.") // 결과: EBNarfcGkAczpeiSJwtUfH9FEVd1xFhdZis83erU9WNu
반환값: base58_encode(sha3_256(data))
verify(algo, message, signature, pubkey)
서명을 검증합니다. ed25519와 secp256k1 알고리즘을 모두 지원합니다.
| 파라미터 | 타입 | 비고 |
|---|---|---|
| algo | string | "ed25519" 또는 "secp256k1" |
| message | string | base58로 인코딩된 서명 대상 원문 |
| signature | string | base58로 인코딩된 검증할 서명 |
| pubkey | string | base58로 인코딩된 서명에 사용된 개인키에 대응하는 공개키 |
- 반환값: int, 1 (성공) 또는 0 (실패)
예시:
// ed25519 알고리즘 사용
// base58 인코딩된 개인키: "4PTQW2hvwZoyuMdgKbo3iQ9mM7DTzxSV54RpeJyycD9b1R1oGgYT9hKoPpAGiLrhYA8sLQ3sAVFoNuMXRsUH7zw6"
// base58 인코딩된 공개키: "2vSjKSXhepo7vmbPQHFcnEvx8mWRFrf46DaTX1Bp3TBi"
// 원문: "hello world"
// "StV1DL6CwTryKyV"는 "hello world"의 base58 인코딩 결과
// "38V8bZC4e78pU7zBN86CF8R8ip76Rhf3vyiwTQR2MVkqHesmUbZJVmN8AE6eWhQg6ekKaa2H4iB4JJibC5stBRrN"는 위 개인키로 서명한 base58 인코딩 결과
// 따라서 검증 결과는 1이어야 합니다.
let v = IOSTCrypto.verify("ed25519", "StV1DL6CwTryKyV", "38V8bZC4e78pU7zBN86CF8R8ip76Rhf3vyiwTQR2MVkqHesmUbZJVmN8AE6eWhQg6ekKaa2H4iB4JJibC5stBRrN", "2vSjKSXhepo7vmbPQHFcnEvx8mWRFrf46DaTX1Bp3TBi"); // v = 1
Float64, Int64, BigNumber 객체
컨트랙트에서는 고정밀 계산을 위해 Float64, Int64, BigNumber를 사용할 수 있습니다.
Float64 API는 여기 에서 확인할 수 있습니다.
Int64 API는 여기 에서 확인할 수 있습니다.
BigNumber API는 여기 에서 확인할 수 있습니다.
예시:
let bonus = new Float64("1.0123456789");
let earning = bonus.div(2).toFixed(8); // earning은 "0.50617283"
blockchain.withdraw("testacc", earning, "");
비활성화된 JavaScript 메서드
보안상의 이유로 일부 JavaScript 기능이 금지되어 있습니다. 이 문서 에서 허용/금지 API 목록을 확인할 수 있습니다.