# Go SDK 浣跨敤璇存槑 <span id="section_sdk"></span> 鏈瘒浠嬬粛锛� 1銆佺幆澧冧緷璧� 2銆乻dk渚濊禆浣跨敤 3銆佹櫘閫氬悎绾﹀畨瑁呫€佽皟鐢� 4銆丒VM鍚堢害瀹夎銆佽皟鐢� 5銆佹洿澶氱殑绀轰緥鍙婂叏閮ㄦ帴鍙� ## 闀垮畨閾維DK姒傝堪 1. 鏁翠綋浠嬬粛 闀垮畨閾綻SDK`鏄笟鍔℃ā鍧椾笌闀垮畨閾句氦浜掔殑妗ユ锛屾敮鎸佸弻鍚慲TLS`璁よ瘉锛屾彁渚涘畨鍏ㄥ彲闈犵殑鍔犲瘑閫氫俊淇¢亾銆� 闀垮畨閾炬彁渚涗簡澶氱璇█鐨刞SDK`锛屽寘鎷細`Go SDK`銆乣Java SDK`銆乣Python SDK`銆乣Nodejs SDK`鏂逛究寮€鍙戣€呮牴鎹渶瑕佽繘琛岄€夌敤銆� 鎻愪緵鐨刞SDK`鎺ュ彛锛岃鐩栧悎绾︾鐞嗐€侀摼閰嶇疆绠$悊銆佽瘉涔︾鐞嗐€佸绛炬敹闆嗐€佸悇绫绘煡璇㈡搷浣溿€佷簨浠惰闃呯瓑鍦烘櫙锛屾弧瓒充簡涓嶅悓鐨勪笟鍔″満鏅渶瑕併€� 2. 鍚嶈瘝姒傚康璇存槑 - **`Node`锛堣妭鐐癸級**锛氫唬琛ㄤ竴涓摼鑺傜偣鐨勫熀鏈俊鎭紝鍖呮嫭锛氳妭鐐瑰湴鍧€銆佽繛鎺ユ暟銆佹槸鍚﹀惎鐢╜TLS`璁よ瘉绛変俊鎭� - **`ChainClient`锛堥摼瀹㈡埛绔級**锛氭墍鏈夊鎴风瀵归摼鑺傜偣鐨勬搷浣滄帴鍙i兘鏉ヨ嚜`ChainClient` - **鍘嬬缉璇佷功**锛氬彲浠ヤ负`ChainClient`寮€鍚瘉涔﹀帇缂╁姛鑳斤紝寮€鍚悗鍙互鍑忓皬浜ゆ槗鍖呭ぇ灏忥紝鎻愬崌澶勭悊鎬ц兘 ## 鐜鍑嗗 ### 杞欢鐜渚濊禆 **golang** 锛� 鐗堟湰涓�1.16鎴栦互涓� 涓嬭浇鍦板潃锛�<https://golang.org/dl/> 鑻ュ凡瀹夎锛岃閫氳繃鍛戒护鏌ョ湅鐗堟湰锛� ```bash $ go version go version go1.16 linux/amd64 ``` ### 涓嬭浇瀹夎sdk 杩涘叆鎮ㄧ殑Go椤圭洰锛屾墽琛屼互涓嬪懡浠ゆ坊鍔犲sdk鐨勫紩鐢細 ```bash go get chainmaker.org/chainmaker/sdk-go/v2@v2.3.3 ``` ### 闀垮畨閾剧幆澧冨噯澶� 鍒涘缓涓€鏉¤瘉涔︽ā寮忕殑闀垮畨閾撅紝骞剁‘淇濈浉鍏宠妭鐐圭綉缁滈€氱晠锛岀浉鍏虫暀绋嬭锛歔銆婇€氳繃鍛戒护琛屼綋楠岄摼銆媇(../quickstart/閫氳繃鍛戒护琛屼綋楠岄摼.md) ## 鎬庝箞浣跨敤SDK ### 绀轰緥浠g爜 #### 鍒涘缓鑺傜偣 璁剧疆鑺傜偣淇℃伅锛屽彲鐢ㄤ綔鍒涘缓涓庤鑺傜偣杩炴帴鐨勫鎴风 ```go // 鍒涘缓鑺傜偣 func createNode(nodeAddr string, connCnt int) *NodeConfig { node := NewNodeConfig( // 鑺傜偣鍦板潃锛屾牸寮忥細127.0.0.1:12301 WithNodeAddr(nodeAddr), // 鑺傜偣杩炴帴鏁� WithNodeConnCnt(connCnt), // 鑺傜偣鏄惁鍚敤TLS璁よ瘉 WithNodeUseTLS(true), // 鏍硅瘉涔﹁矾寰勶紝鏀寔澶氫釜 WithNodeCAPaths(caPaths), // TLS Hostname WithNodeTLSHostName(tlsHostName), ) return node } ``` #### 浠ュ弬鏁板舰寮忓垱寤篊hainClient > 鏇村鍐呭璇峰弬鐪嬶細`sdk_client_test.go` > > 娉細绀轰緥涓瘉涔﹂噰鐢ㄨ矾寰勬柟寮忓幓璁剧疆锛屼篃鍙互浣跨敤璇佷功鍐呭鍘昏缃紝鍏蜂綋璇峰弬鐪媊createClientWithCaCerts`鏂规硶 ```go // 鍒涘缓ChainClient func createClient() (*ChainClient, error) { if node1 == nil { // 鍒涘缓鑺傜偣1 node1 = createNode(nodeAddr1, connCnt1) } if node2 == nil { // 鍒涘缓鑺傜偣2 node2 = createNode(nodeAddr2, connCnt2) } chainClient, err := NewChainClient( // 璁剧疆褰掑睘缁勭粐 WithChainClientOrgId(chainOrgId), // 璁剧疆閾綢D WithChainClientChainId(chainId), // 璁剧疆logger鍙ユ焺锛岃嫢涓嶈缃紝灏嗛噰鐢ㄩ粯璁ゆ棩蹇楁枃浠惰緭鍑烘棩蹇� WithChainClientLogger(getDefaultLogger()), // 璁剧疆瀹㈡埛绔敤鎴风閽ヨ矾寰� WithUserKeyFilePath(userKeyPath), // 璁剧疆瀹㈡埛绔敤鎴疯瘉涔� WithUserCrtFilePath(userCrtPath), // 娣诲姞鑺傜偣1 AddChainClientNodeConfig(node1), // 娣诲姞鑺傜偣2 AddChainClientNodeConfig(node2), ) if err != nil { return nil, err } //鍚敤璇佷功鍘嬬缉锛堝紑鍚瘉涔﹀帇缂╁彲浠ュ噺灏忎氦鏄撳寘澶у皬锛屾彁鍗囧鐞嗘€ц兘锛� err = chainClient.EnableCertHash() if err != nil { log.Fatal(err) } return chainClient, nil } ``` #### 浠ラ厤缃枃浠跺舰寮忓垱寤篊hainClient > 娉細鍙傛暟褰㈠紡鍜岄厤缃枃浠跺舰寮忎袱涓彲浠ュ悓鏃朵娇鐢紝鍚屾椂閰嶇疆鏃讹紝浠ュ弬鏁颁紶鍏ヤ负鍑� ```go func createClientWithConfig() (*ChainClient, error) { chainClient, err := NewChainClient( WithConfPath("./testdata/sdk_config.yml"), ) if err != nil { return nil, err } //鍚敤璇佷功鍘嬬缉锛堝紑鍚瘉涔﹀帇缂╁彲浠ュ噺灏忎氦鏄撳寘澶у皬锛屾彁鍗囧鐞嗘€ц兘锛� err = chainClient.EnableCertHash() if err != nil { return nil, err } return chainClient, nil } ``` #### 閮ㄧ讲wasm鍚堢害 涓嬫枃锛屽皢婕旂ず閫氳繃sdk閮ㄧ讲wasm鍚堢害锛� > `sdk_user_contract_claim_test.go` ```go func testUserContractClaimCreate(t *testing.T, client *ChainClient, admin1, admin2, admin3, admin4 *ChainClient, withSyncResult bool, isIgnoreSameContract bool) { resp, err := createUserContract(client, admin1, admin2, admin3, admin4, claimContractName, claimVersion, claimByteCodePath, common.RuntimeType_WASMER, []*common.KeyValuePair{}, withSyncResult) if !isIgnoreSameContract { require.Nil(t, err) } fmt.Printf("CREATE claim contract resp: %+v\n", resp) } func createUserContract(client *ChainClient, admin1, admin2, admin3, admin4 *ChainClient, contractName, version, byteCodePath string, runtime common.RuntimeType, kvs []*common.KeyValuePair, withSyncResult bool) (*common.TxResponse, error) { payloadBytes, err := client.CreateContractCreatePayload(contractName, version, byteCodePath, runtime, kvs) if err != nil { return nil, err } // 鍚勭粍缁嘇dmin鏉冮檺鐢ㄦ埛绛惧悕 signedPayloadBytes1, err := admin1.SignContractManagePayload(payloadBytes) if err != nil { return nil, err } signedPayloadBytes2, err := admin2.SignContractManagePayload(payloadBytes) if err != nil { return nil, err } signedPayloadBytes3, err := admin3.SignContractManagePayload(payloadBytes) if err != nil { return nil, err } signedPayloadBytes4, err := admin4.SignContractManagePayload(payloadBytes) if err != nil { return nil, err } // 鏀堕泦骞跺悎骞剁鍚� mergeSignedPayloadBytes, err := client.MergeContractManageSignedPayload([][]byte{signedPayloadBytes1, signedPayloadBytes2, signedPayloadBytes3, signedPayloadBytes4}) if err != nil { return nil, err } // 鍙戦€佸垱寤哄悎绾﹁姹� resp, err := client.SendContractManageRequest(mergeSignedPayloadBytes, createContractTimeout, withSyncResult) if err != nil { return nil, err } err = checkProposalRequestResp(resp, true) if err != nil { return nil, err } return resp, nil ``` #### 璋冪敤wasm鍚堢害 涓嬫枃锛屽皢婕旂ず閫氳繃sdk璋冪敤wasm鍚堢害锛� > `sdk_user_contract_claim_test.go` ```go func testUserContractClaimInvoke(client *ChainClient, method string, withSyncResult bool) (string, error) { curTime := fmt.Sprintf("%d", CurrentTimeMillisSeconds()) fileHash := uuid.GetUUID() params := map[string]string{ "time": curTime, "file_hash": fileHash, "file_name": fmt.Sprintf("file_%s", curTime), } err := invokeUserContract(client, claimContractName, method, "", params, withSyncResult) if err != nil { return "", err } return fileHash, nil } func invokeUserContract(client *ChainClient, contractName, method, txId string, params map[string]string, withSyncResult bool) error { resp, err := client.InvokeContract(contractName, method, txId, params, -1, withSyncResult) if err != nil { return err } if resp.Code != common.TxStatusCode_SUCCESS { return fmt.Errorf("invoke contract failed, [code:%d]/[msg:%s]\n", resp.Code, resp.Message) } if !withSyncResult { fmt.Printf("invoke contract success, resp: [code:%d]/[msg:%s]/[txId:%s]\n", resp.Code, resp.Message, resp.ContractResult.Result) } else { fmt.Printf("invoke contract success, resp: [code:%d]/[msg:%s]/[contractResult:%s]\n", resp.Code, resp.Message, resp.ContractResult) } return nil } ``` #### 鍒涘缓鍙婅皟鐢╡vm鍚堢害 > `sdk-go/examples/user_contract_evm_balance/main.go`(<https://git.chainmaker.org.cn/chainmaker/sdk-go/-/blob/master/examples/user_contract_evm_balance/main.go>) ### 鏇村绀轰緥鍜岀敤娉� > 鏇村绀轰緥鍜岀敤娉曪紝璇峰弬鐪嬪崟鍏冩祴璇曠敤渚� <br>绀轰緥: (<https://git.chainmaker.org.cn/chainmaker/sdk-go/-/blob/master/examples>) | 鍔熻兘 | 鍗曟祴浠g爜 | | -------- | ----------------------------- | | 鐢ㄦ埛鍚堢害 | `sdk_user_contract_test.go` | | 绯荤粺鍚堢害 | `sdk_system_contract_test.go` | | 閾鹃厤缃� | `sdk_chain_config_test.go` | | 璇佷功绠$悊 | `sdk_cert_manage_test.go` | | 娑堟伅璁㈤槄 | `sdk_subscribe_test.go` | ### demo sdk-go demo鍙傝€冿細 [鏂囦欢 路 v2.3.2 路 chainmaker / sdk-go-demo 路 ChainMaker](https://git.chainmaker.org.cn/chainmaker/sdk-go-demo/-/tree/v2.3.2) ## 鎺ュ彛璇存槑 璇峰弬鐪嬶細[銆奵hainmaker-go-sdk銆媇(https://git.chainmaker.org.cn/chainmaker/sdk-go/-/blob/v2.3.3/sdk_interface.md) 鎵€鏈塯o-sdk鎺ュ彛鍙傝€冿細 https://git.chainmaker.org.cn/chainmaker/sdk-go/-/blob/v2.3.3/sdk_interface.go