以太坊ETH-智能合约开发-solidity源码分析-truffle进阶

2024-05-07 13:32

本文主要是介绍以太坊ETH-智能合约开发-solidity源码分析-truffle进阶,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

0. 背景

上一篇文章我们从合约编写、编译、部署、交互等几个方面介绍了truffle的大致用法。
本篇主要继续深入地介绍truffle的高级用法 + 合约源码分析

1. 将合约部署到测试网Ropsten

1.1 注册infura获取API-KEY

infura是基于ETH的chain公共API服务,为开发者提供链上数据查询、交易广播等功能。

1.2 准备助记词

可从Web钱包MetaMask 上进行创建并导出助记词
一个助记词可以对应多个网络环境的地址,请勿向助记词对应的地址转入主网的ETH,否则有一定的安全风险

1.3 安装 truffle-hdwallet-provider

由于需要将合约部署到测试网Ropsten,此过程需要部署者私钥进行签名再将数据进行广播,truffle-hdwallet-providertruffle上提供交易离线签名的模块
:必须在truffle框架的代码目录下安装,否则不生效

 ✘ wujinquan@wujinquandeMacBook-Pro  ~/workspace/eth/truffle/defi  npm install truffle-hdwallet-provider
npm WARN deprecated truffle-hdwallet-provider@1.0.17: WARNING: This package has been renamed to @truffle/hdwallet-provider.
npm WARN deprecated request@2.88.2: request has been deprecated, see https://github.com/request/request/issues/3142> websocket@1.0.29 install /Users/wujinquan/workspace/eth/truffle/defi/node_modules/web3-providers-ws/node_modules/websocket
> (node-gyp rebuild 2> builderror.log) || (exit 0)CXX(target) Release/obj.target/bufferutil/src/bufferutil.o> websocket@1.0.31 install /Users/wujinquan/workspace/eth/truffle/defi/node_modules/websocket
> (node-gyp rebuild 2> builderror.log) || (exit 0)CXX(target) Release/obj.target/bufferutil/src/bufferutil.oSOLINK_MODULE(target) Release/bufferutil.nodeCXX(target) Release/obj.target/validation/src/validation.oSOLINK_MODULE(target) Release/validation.node
npm WARN saveError ENOENT: no such file or directory, open '/Users/wujinquan/workspace/eth/truffle/defi/package.json'
npm notice created a lockfile as package-lock.json. You should commit this file.
npm WARN enoent ENOENT: no such file or directory, open '/Users/wujinquan/workspace/eth/truffle/defi/package.json'
npm WARN defi No description
npm WARN defi No repository field.
npm WARN defi No README data
npm WARN defi No license field.+ truffle-hdwallet-provider@1.0.17
added 326 packages from 212 contributors and audited 20646 packages in 114.122s
found 2 vulnerabilities (1 low, 1 high)run `npm audit fix` to fix them, or `npm audit` for details╭────────────────────────────────────────────────────────────────╮│                                                                ││      New minor version of npm available! 6.13.4 → 6.14.2       ││   Changelog: https://github.com/npm/cli/releases/tag/v6.14.2   ││               Run npm install -g npm to update!                ││                                                                │╰────────────────────────────────────────────────────────────────╯wujinquan@wujinquandeMacBook-Pro  ~/workspace/eth/truffle/defi  ls
build             defi              node_modules      test
contracts         migrations        package-lock.json truffle-config.jswujinquan@wujinquandeMacBook-Pro  ~/workspace/eth/truffle/defi 
1.4 修改truffle配置

主要修改ropsten网络配置,使truffle能顺利与ropsten交互

/*** Use this file to configure your truffle project. It's seeded with some* common settings for different networks and features like migrations,* compilation and testing. Uncomment the ones you need or modify* them to suit your project as necessary.** More information about configuration can be found at:** truffleframework.com/docs/advanced/configuration** To deploy via Infura you'll need a wallet provider (like @truffle/hdwallet-provider)* to sign your transactions before they're sent to a remote public node. Infura accounts* are available for free at: infura.io/register.** You'll also need a mnemonic - the twelve word phrase the wallet uses to generate* public/private key pairs. If you're publishing your code to GitHub make sure you load this* phrase from a file you've .gitignored so it doesn't accidentally become public.**/const HDWalletProvider = require("truffle-hdwallet-provider");
// const infuraKey = "fj4jll3k.....";
//
// const fs = require('fs');
// const mnemonic = fs.readFileSync(".secret").toString().trim();
const mnemonic = "grant boat distance require trap pair theme together spray blush glory simple"
//0x843ACfB41E5c0F1E0587C5B765d897cCDeA8c4DDmodule.exports = {/*** Networks define how you connect to your ethereum client and let you set the* defaults web3 uses to send transactions. If you don't specify one truffle* will spin up a development blockchain for you on port 9545 when you* run `develop` or `test`. You can ask a truffle command to use a specific* network from the command line, e.g** $ truffle test --network <network-name>*/networks: {// Useful for testing. The `development` name is special - truffle uses it by default// if it's defined here and no other network is specified at the command line.// You should run a client (like ganache-cli, geth or parity) in a separate terminal// tab if you use this network and you must also set the `host`, `port` and `network_id`// options below to some value.//// development: {//  host: "127.0.0.1",     // Localhost (default: none)//  port: 8545,            // Standard Ethereum port (default: none)//  network_id: "*",       // Any network (default: none)// },// Another network with more advanced options...// advanced: {// port: 8777,             // Custom port// network_id: 1342,       // Custom network// gas: 8500000,           // Gas sent with each transaction (default: ~6700000)// gasPrice: 20000000000,  // 20 gwei (in wei) (default: 100 gwei)// from: <address>,        // Account to send txs from (default: accounts[0])// websockets: true        // Enable EventEmitter interface for web3 (default: false)// },// Useful for deploying to a public network.// NB: It's important to wrap the provider as a function.ropsten: {provider: () => new HDWalletProvider(mnemonic, `https://ropsten.infura.io/v3/5c93axxx`),//示例无效network_id: 3,       // Ropsten's idgas: 5500000,        // Ropsten has a lower block limit than mainnetconfirmations: 2,    // # of confs to wait between deployments. (default: 0)timeoutBlocks: 200,  // # of blocks before a deployment times out  (minimum/default: 50)skipDryRun: true     // Skip dry run before migrations? (default: false for public nets )}// Useful for private networks// private: {// provider: () => new HDWalletProvider(mnemonic, `https://network.io`),// network_id: 2111,   // This network is yours, in the cloud.// production: true    // Treats this network as if it was a public net. (default: false)// }},// Set default mocha options here, use special reporters etc.mocha: {// timeout: 100000},// Configure your compilerscompilers: {solc: {// version: "0.5.1",    // Fetch exact version from solc-bin (default: truffle's version)// docker: true,        // Use "0.5.1" you've installed locally with docker (default: false)// settings: {          // See the solidity docs for advice about optimization and evmVersion//  optimizer: {//    enabled: false,//    runs: 200//  },//  evmVersion: "byzantium"// }}}
}
1.5 部署至Ropsten

执行truffle migrate --network ropsten --reset 即可部署至Ropsten
如需要重新编译所有合约,可执行truffle migrate --network ropsten --reset --compile-all

 wujinquan@wujinquandeMacBook-Pro  ~/workspace/eth/truffle/defi  truffle migrate --network ropsten --resetCompiling your contracts...
===========================
> Everything is up to date, there is nothing to compile.Starting migrations...
======================
> Network name:    'ropsten'
> Network id:      3
> Block gas limit: 0x7a121d1_initial_migration.js
======================Replacing 'Migrations'----------------------> transaction hash:    0x349ca58d8ed2176265efc58bf232878d930c71436a9b39796062489a638de396> Blocks: 2            Seconds: 92> contract address:    0x619DB4dda0cd2b3fF6351F52828Af5Cc44E6cA55> block number:        7531302> block timestamp:     1584376631> account:             0x843ACfB41E5c0F1E0587C5B765d897cCDeA8c4DD> balance:             0.47030684> gas used:            164175> gas price:           20 gwei> value sent:          0 ETH> total cost:          0.0032835 ETHPausing for 2 confirmations...------------------------------> confirmation number: 1 (block: 7531303)> confirmation number: 3 (block: 7531305)> Saving migration to chain.> Saving artifacts-------------------------------------> Total cost:           0.0032835 ETH2_deploy_contracts.js
=====================Replacing 'DeFi'----------------> transaction hash:    0x4be50b4e7a560080de6587078f937a553f29ac7b04ccd2e6b3802dc75dc8fe61> Blocks: 1            Seconds: 63> contract address:    0xB378420cde84c7A73EecfAeE2fC91ED364F45E9F> block number:        7531309> block timestamp:     1584376852> account:             0x843ACfB41E5c0F1E0587C5B765d897cCDeA8c4DD> balance:             0.4474762> gas used:            1099191> gas price:           20 gwei> value sent:          0 ETH> total cost:          0.02198382 ETHPausing for 2 confirmations...------------------------------> confirmation number: 1 (block: 7531310)> confirmation number: 2 (block: 7531311)> Saving migration to chain.> Saving artifacts-------------------------------------> Total cost:          0.02198382 ETHSummary
=======
> Total deployments:   2
> Final cost:          0.02526732 ETHwujinquan@wujinquandeMacBook-Pro  ~/workspace/eth/truffle/defi 
1.6 从区块浏览器上查看已部署的合约

从log输出可见DeFi合约地址为0xB378420cde84c7A73EecfAeE2fC91ED364F45E9F

2. 合约源码分析

项目源码可见Github仓库,主要分析DeFi.sol,过程以下代码中的详细中英文注释

pragma solidity >=0.4.25 <0.7.0;contract Token{mapping (address => uint256) balances;string  public name;string  public symbol;uint8   public decimals;uint256 public totalSupply;mapping (address => mapping (address => uint256)) allowed;//ERC20 Token Standard: https://eips.ethereum.org/EIPS/eip-20constructor() public { name = "Token";                                         	// Set the name symbol = "TK";                                              // Set the symbol decimals = 18;                                              // Amount of decimals for display purposes
//		totalSupply = 1000000000000000000000;                       // Not set total supply	}//Returns the account balance of another account with address _owner.function balanceOf(address _owner) public view returns (uint256 balance) {return balances[_owner];	}/* Transfers _value amount of tokens to address _to, and MUST fire the Transfer event. The function SHOULD throw if the message caller’s account balance does not have enough tokens to spend.Note Transfers of 0 values MUST be treated as normal transfers and fire the Transfer event.*/function transfer(address _to, uint256 _value) public returns (bool success) {require(_value > 0 );                                      // Check if token's value to be send > 0require(balances[msg.sender] >= _value);                   // Check if the sender has enough tokenrequire(balances[_to] + _value > balances[_to]);           // Check for overflows											balances[msg.sender] -= _value;                            // Subtract token from the senderbalances[_to] += _value;                                   // Add the same amount to the receiver                      emit Transfer(msg.sender, _to, _value); 				   // Notify anyone listening that this transaction happen.return true;      }/* The transferFrom method is used for a withdraw workflow, allowing contracts to transfer tokens on your behalf. This can be used for example to allow a contract to transfer tokens on your behalf and/or to charge fees in sub-currencies. The function SHOULD throw unless the _from account has deliberately authorized the sender of the message via some mechanism.Note Transfers of 0 values MUST be treated as normal transfers and fire the Transfer event.*/function transferFrom(address _from, address _to, uint256 _value) public returns (bool success) {require(balances[_from] >= _value);                 // Check if the sender has enough tokenrequire(balances[_to] + _value >= balances[_to]);   // Check for overflowsrequire(_value <= allowed[_from][msg.sender]);      // Check allowancebalances[_from] -= _value;                          // Subtract from the senderbalances[_to] += _value;                            // Add the same amount to the receiverallowed[_from][msg.sender] -= _value;emit Transfer(_from, _to, _value);return true;}/* Allows _spender to withdraw from your account multiple times, up to the _value amount. If this function is called again it overwrites the current allowance with _value.NOTE: To prevent attack vectors like the one described here and discussed here, clients SHOULD make sure to create user interfaces in such a way that they set the allowance first to 0 before setting it to another value for the same spender. THOUGH The contract itself shouldn’t enforce it, to allow backwards compatibility with contracts deployed before */function approve(address _spender, uint256 _value) public returns (bool success) {require(balances[msg.sender] >= _value);allowed[msg.sender][_spender] = _value;emit Approval(msg.sender, _spender, _value);return true;}//Returns the amount which _spender is still allowed to withdraw from _owner.function allowance(address _owner, address _spender) public view returns (uint256 remaining) {return allowed[_owner][_spender];}//The event for tranfer and approveevent Transfer(address indexed _from, address indexed _to, uint256 _value);event Approval(address indexed _owner, address indexed _spender, uint256 _value);
}contract DeFi is Token{ //声明owner,暂时没作用address public owner ;//声明 用户-抵押ETH数量 mappingmapping (address => uint) pledgeETHAmount;//声明 抵押/赎回时的eventevent Pledge(address user, uint256 amount);event Redeem(address user, uint256 amount);//构造函数,只在合约被部署的时候执行一次constructor() public {owner = msg.sender ;}//抵押功能function pledge() public payable returns(bool success){//ETH抵押金额必须大于0require(msg.value > 0, "Not enough ETH to pledge.");//抵押操作// 1. 1:1贷出ERC20 TokenToken.balances[msg.sender] += msg.value;// 2. 写入抵押信息map,记录用户抵押ETH的数量:单位weipledgeETHAmount[msg.sender] += msg.value;// 3. 更新Token总量Token.totalSupply += msg.value;//记录抵押事件emit Pledge(msg.sender,msg.value);return true;}//赎回功能function redeem(uint256 value) public returns(bool success){//要求赎回ETH的数量必须 <= Token余额require(value <= Token.balances[msg.sender],"Not enough ETH to redeem.");//赎回操作// 1. 在合约转出ETH到用户地址之前将待发金额清零,更新用户Token余额和Token总量,来防止重入(re-entrancy)攻击Token.balances[msg.sender] -= value;Token.totalSupply -=  value;// 2. 从合约里转ETH到对应用户msg.sender.transfer(value);//记录赎回事件emit Redeem(msg.sender,value);return true;}
}

3. 与合约交互

在项目目录中执行truffle console --network ropsten连接ropsten并进入console模式

3.0 定义常用的抽象合约对象
truffle(ropsten)> let defi = await DeFi.deployed()  //合约对象定义为defi
undefined
truffle(ropsten)> let contractaddr = await defi.address 合约地址定义为contractaddr
undefined
truffle(ropsten)>
3.1 调用合约抵押ETH贷出ERC20代币TK

可见区块浏览器https://ropsten.etherscan.io/tx/0x6dcb3790976b0d3a6f0715739a3c771f192f39b3f1d2995a88f718d6df30c6d9

truffle(ropsten)> defi.pledge.sendTransaction({from:accounts[0],value:101}) //指定sender和抵押ETH数量,回显需要一点时间
{tx: '0x6dcb3790976b0d3a6f0715739a3c771f192f39b3f1d2995a88f718d6df30c6d9',receipt: {blockHash: '0x15b79d45581d83e7f5aaa40a9fac51c13d1824f188869207948c050fc4ded8ae',blockNumber: 7531333,contractAddress: null,cumulativeGasUsed: 85311,from: '0x843acfb41e5c0f1e0587c5b765d897ccdea8c4dd',gasUsed: 85311,logs: [ [Object] ],logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000200000000000000000000000000000000000040000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',status: true,to: '0xb378420cde84c7a73eecfaee2fc91ed364f45e9f',transactionHash: '0x6dcb3790976b0d3a6f0715739a3c771f192f39b3f1d2995a88f718d6df30c6d9',transactionIndex: 0,rawLogs: [ [Object] ]},logs: [{address: '0xB378420cde84c7A73EecfAeE2fC91ED364F45E9F',blockHash: '0x15b79d45581d83e7f5aaa40a9fac51c13d1824f188869207948c050fc4ded8ae',blockNumber: 7531333,logIndex: 0,removed: false,transactionHash: '0x6dcb3790976b0d3a6f0715739a3c771f192f39b3f1d2995a88f718d6df30c6d9',transactionIndex: 0,id: 'log_818726e7',event: 'Pledge',args: [Result]}]
}
truffle(ropsten)>
3.2 查询合约余额和用户的Token余额是否达到预期
truffle(ropsten)> web3.eth.getBalance(contractaddr) //合约的ETH余额
'101'
truffle(ropsten)> defi.balanceOf(accounts[0]) //用户的Token余额
BN {negative: 0,words: [ 101, <1 empty item> ],length: 1,red: null
}
truffle(ropsten)>
3.3 调用合约归还ERC20代币TK,赎回ETH

可见区块浏览器https://ropsten.etherscan.io/tx/0xa720d3da5eda30b9a816e68aaf41ddde0a536c2307734317f6b15243fb9b1829

truffle(ropsten)> defi.redeem.sendTransaction(99,{from:accounts[0]})  //归还99`TK`,1比1 赎回99`wei``ETH`
Error: Invalid JSON RPC response: ""at Object.InvalidResponse (/Users/wujinquan/workspace/eth/truffle/defi/node_modules/truffle-hdwallet-provider/dist/webpack:/truffle-hdwallet-provider/Users/gnidan/src/work/truffle/node_modules/web3/node_modules/web3-core-helpers/src/errors.js:42:1)at t.InvalidResponse [as onreadystatechange] (/Users/wujinquan/workspace/eth/truffle/defi/node_modules/truffle-hdwallet-provider/dist/webpack:/truffle-hdwallet-provider/Users/gnidan/src/work/truffle/node_modules/web3/node_modules/web3-providers-http/src/index.js:92:1)at t._a [as dispatchEvent] (/Users/wujinquan/workspace/eth/truffle/defi/node_modules/truffle-hdwallet-provider/dist/webpack:/truffle-hdwallet-provider/Users/gnidan/src/work/truffle/node_modules/xhr2-cookies/dist/xml-http-request-event-target.js:27:61)at t.dispatchEvent [as _setReadyState] (/Users/wujinquan/workspace/eth/truffle/defi/node_modules/truffle-hdwallet-provider/dist/webpack:/truffle-hdwallet-provider/Users/gnidan/src/work/truffle/node_modules/xhr2-cookies/dist/xml-http-request.js:208:1)at t._setReadyState [as _onHttpRequestError] (/Users/wujinquan/workspace/eth/truffle/defi/node_modules/truffle-hdwallet-provider/dist/webpack:/truffle-hdwallet-provider/Users/gnidan/src/work/truffle/node_modules/xhr2-cookies/dist/xml-http-request.js:349:1)at ClientRequest._onHttpRequestError (/Users/wujinquan/workspace/eth/truffle/defi/node_modules/truffle-hdwallet-provider/dist/webpack:/truffle-hdwallet-provider/Users/gnidan/src/work/truffle/node_modules/xhr2-cookies/dist/xml-http-request.js:252:47)at ClientRequest.emit (events.js:305:20)at ClientRequest.EventEmitter.emit (domain.js:483:12)at TLSSocket.socketErrorListener (_http_client.js:423:9)at TLSSocket.emit (events.js:305:20)at TLSSocket.EventEmitter.emit (domain.js:483:12)at emitErrorNT (internal/streams/destroy.js:84:8)at processTicksAndRejections (internal/process/task_queues.js:84:21)
{tx: '0xa720d3da5eda30b9a816e68aaf41ddde0a536c2307734317f6b15243fb9b1829',receipt: {blockHash: '0x0a08ef737e0729f31a2bd428eb50273833f669ebfc95b622cdf405c67996ceef',blockNumber: 7531341,contractAddress: null,cumulativeGasUsed: 756933,from: '0x843acfb41e5c0f1e0587c5b765d897ccdea8c4dd',gasUsed: 43116,logs: [ [Object] ],logsBloom: '0x00000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000040000000000000000000000000000000040000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000',status: true,to: '0xb378420cde84c7a73eecfaee2fc91ed364f45e9f',transactionHash: '0xa720d3da5eda30b9a816e68aaf41ddde0a536c2307734317f6b15243fb9b1829',transactionIndex: 1,rawLogs: [ [Object] ]},logs: [{address: '0xB378420cde84c7A73EecfAeE2fC91ED364F45E9F',blockHash: '0x0a08ef737e0729f31a2bd428eb50273833f669ebfc95b622cdf405c67996ceef',blockNumber: 7531341,logIndex: 1,removed: false,transactionHash: '0xa720d3da5eda30b9a816e68aaf41ddde0a536c2307734317f6b15243fb9b1829',transactionIndex: 1,id: 'log_2be7cb64',event: 'Redeem',args: [Result]}]
}
truffle(ropsten)>
3.4 查询赎回后合约余额和用户的Token余额是否达到预期
truffle(ropsten)> web3.eth.getBalance(contractaddr) //合约的ETH余额
'2'
truffle(ropsten)> defi.balanceOf(accounts[0]) //用户的Token余额
BN { negative: 0, words: [ 2, <1 empty item> ], length: 1, red: null }
truffle(ropsten)>

4.其它部署调试工具

对于开发者而言,可使用可视化工具Remix进行合约调试、部署
同一例子,详细参考以太坊ETH-智能合约开发-Remix使用

这篇关于以太坊ETH-智能合约开发-solidity源码分析-truffle进阶的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/967483

相关文章

RedHat运维-Linux文本操作基础-AWK进阶

你不用整理,跟着敲一遍,有个印象,然后把它保存到本地,以后要用再去看,如果有了新东西,你自个再添加。这是我参考牛客上的shell编程专项题,只不过换成了问答的方式而已。不用背,就算是我自己亲自敲,我现在好多也记不住。 1. 输出nowcoder.txt文件第5行的内容 2. 输出nowcoder.txt文件第6行的内容 3. 输出nowcoder.txt文件第7行的内容 4. 输出nowcode

【Linux进阶】UNIX体系结构分解——操作系统,内核,shell

1.什么是操作系统? 从严格意义上说,可将操作系统定义为一种软件,它控制计算机硬件资源,提供程序运行环境。我们通常将这种软件称为内核(kerel),因为它相对较小,而且位于环境的核心。  从广义上说,操作系统包括了内核和一些其他软件,这些软件使得计算机能够发挥作用,并使计算机具有自己的特生。这里所说的其他软件包括系统实用程序(system utility)、应用程序、shell以及公用函数库等

[职场] 公务员的利弊分析 #知识分享#经验分享#其他

公务员的利弊分析     公务员作为一种稳定的职业选择,一直备受人们的关注。然而,就像任何其他职业一样,公务员职位也有其利与弊。本文将对公务员的利弊进行分析,帮助读者更好地了解这一职业的特点。 利: 1. 稳定的职业:公务员职位通常具有较高的稳定性,一旦进入公务员队伍,往往可以享受到稳定的工作环境和薪资待遇。这对于那些追求稳定的人来说,是一个很大的优势。 2. 薪资福利优厚:公务员的薪资和

Eclipse+ADT与Android Studio开发的区别

下文的EA指Eclipse+ADT,AS就是指Android Studio。 就编写界面布局来说AS可以边开发边预览(所见即所得,以及多个屏幕预览),这个优势比较大。AS运行时占的内存比EA的要小。AS创建项目时要创建gradle项目框架,so,创建项目时AS比较慢。android studio基于gradle构建项目,你无法同时集中管理和维护多个项目的源码,而eclipse ADT可以同时打开

springboot家政服务管理平台 LW +PPT+源码+讲解

3系统的可行性研究及需求分析 3.1可行性研究 3.1.1技术可行性分析 经过大学四年的学习,已经掌握了JAVA、Mysql数据库等方面的编程技巧和方法,对于这些技术该有的软硬件配置也是齐全的,能够满足开发的需要。 本家政服务管理平台采用的是Mysql作为数据库,可以绝对地保证用户数据的安全;可以与Mysql数据库进行无缝连接。 所以,家政服务管理平台在技术上是可以实施的。 3.1

Python应用开发——30天学习Streamlit Python包进行APP的构建(9)

st.area_chart 显示区域图。 这是围绕 st.altair_chart 的语法糖。主要区别在于该命令使用数据自身的列和指数来计算图表的 Altair 规格。因此,在许多 "只需绘制此图 "的情况下,该命令更易于使用,但可定制性较差。 如果 st.area_chart 无法正确猜测数据规格,请尝试使用 st.altair_chart 指定所需的图表。 Function signa

智能客服到个人助理,国内AI大模型如何改变我们的生活?

引言 随着人工智能(AI)技术的高速发展,AI大模型越来越多地出现在我们的日常生活和工作中。国内的AI大模型在过去几年里取得了显著的进展,不少独创的技术点和实际应用令人瞩目。 那么,国内的AI大模型有哪些独创的技术点?它们在实际应用中又有哪些出色表现呢?此外,普通人又该如何利用这些大模型提升工作和生活的质量和效率呢?本文将为你一一解析。 一、国内AI大模型的独创技术点 多模态学习 多

高仿精仿愤怒的小鸟android版游戏源码

这是一款很完美的高仿精仿愤怒的小鸟android版游戏源码,大家可以研究一下吧、 为了报复偷走鸟蛋的肥猪们,鸟儿以自己的身体为武器,仿佛炮弹一样去攻击肥猪们的堡垒。游戏是十分卡通的2D画面,看着愤怒的红色小鸟,奋不顾身的往绿色的肥猪的堡垒砸去,那种奇妙的感觉还真是令人感到很欢乐。而游戏的配乐同样充满了欢乐的感觉,轻松的节奏,欢快的风格。 源码下载

高度内卷下,企业如何通过VOC(客户之声)做好竞争分析?

VOC,即客户之声,是一种通过收集和分析客户反馈、需求和期望,来洞察市场趋势和竞争对手动态的方法。在高度内卷的市场环境下,VOC不仅能够帮助企业了解客户的真实需求,还能为企业提供宝贵的竞争情报,助力企业在竞争中占据有利地位。 那么,企业该如何通过VOC(客户之声)做好竞争分析呢?深圳天行健企业管理咨询公司解析如下: 首先,要建立完善的VOC收集机制。这包括通过线上渠道(如社交媒体、官网留言

基于 Java 实现的智能客服聊天工具模拟场景

服务端代码 import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.io.PrintWriter;import java.net.ServerSocket;import java.net.Socket;public class Serv