truncate is DDL so there is no way you can include that as *part* of a transaction - it is always a transaction in its own right.
To overcome this, you could look at a mechanism where you shift that out of the process. For example (using your "TABLE1" as the targert)
rename TABLE1 to HIDDEN_TABLE1;
create view TABLE1 as
select * from HIDDEN_TABLE1;
create table HIDDEN_TABLE2 as
select * from HIDDEN_TABLE1;
Now you have 2 copies of the table, and the view points to one of them.
Then your process becomes:
truncate HIDDEN_TABLE2
insert into HIDDEN_TABLE2 select * from XXX@dblink;
If this works to completion, you then do:
create or replace view TABLE1 as
select * from HIDDEN_TABLE2;
to now point to the new data. The next time you run the job, you do the reverse
truncate HIDDEN_TABLE1
insert into HIDDEN_TABLE1 select * from XXX@dblink;
create or replace view TABLE1 as
select * from HIDDEN_TABLE1;