# LoggerNFT as a Digitial Twin
:::info
:bulb: ***NOTE:*** address and public key are used interchangeably
:::
## Outline
- for each physical logger, there is a corresponding NFT (its Digital Twin)
- the physical logger has a [public/private key pair](https://www.ledger.com/academy/blockchain/what-are-public-keys-and-private-keys) allowing it to sign transactions
- in the `LoggerNFT` contract, the loggers variable is mapping of the `loggerId` and the [public key](https://ethereum.org/en/glossary/#public-key) of the physical logger
- before the physical device can log data to the NFT, the `newJob()` function needs to be called along with an `amount` of USDC, `loggerID` of the NFT, and duration to job
:::danger
the insurance protocol will call the `newJob()` function. For now just assume that there is a insurance protocol and it is paying our company to maintain the phiscial hardware as well as paying NFT owners by calling this function
:::
- when the logger is switched on it will sign the data it receives from its sensors with its [private key](https://www.ledger.com/academy/blockchain/what-are-public-keys-and-private-keys) and pass it to the `logData()` function with its `loggerId`
- if the NFT has an active job it will accept the transaction and record the result and emit an event on chain
- each NFT has an `owner`
- this owner can claim any revenue accrued to their NFT by calling the `claim()` function
- the owner can also transfer ownership via the `transfer()` function
<br>
## Pseudo-code
This is just pseudo code. This is kind of what the NFT would look like but there will be a bunch more variables and functions but this is the basic outline
```solidity
contract LoggerNFT {
// state
uint lastLoggerId; // the total number of loggers
mapping (address => uint) owners // mapping of owner addresses to loggerID's
mapping (address => uint) loggers // mapping of logger addresses to loggerID's
// Modifiers
modifier onlyOwner() // if the caller of the function != owner then the function reverts
modifier onlyLogger() // if the caller of the function != logger then the function reverts
// functions
function newLogger(owner, logger) returns (loggerId) // create a new digitial twin for a logger, reurns its NFT ID
function newJob(amount, loggerId, startDate, endDate) // called by the insurance protocol, when the customer buys a policy
function claim(loggerId) onlyOwner returns (amount) // transfers all clamable USDC for the owner of the loggerID
function transfer(newOwner) onlyOwner // allows the owner to transfer ownership
function logData(data[], loggerId) onlyLogger // called by the logger to publish its data on chain
}
```